From foo@baz Tue Apr 9 12:12:43 2002 Date: Tue, 09 Apr 2002 12:14:34 -0700 To: Greg KH From: Greg Kroah-Hartman Subject: Greg's test driver core / sysfs stress test module Don't mess with it, it's horrible. Signed-off-by: Greg Kroah-Hartman --- drivers/Makefile | 3 drivers/gregkh/Makefile | 1 drivers/gregkh/gregkh.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+) --- gregkh-2.6.orig/drivers/Makefile +++ gregkh-2.6/drivers/Makefile @@ -76,3 +76,6 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ + +obj-y += gregkh/ + --- /dev/null +++ gregkh-2.6/drivers/gregkh/Makefile @@ -0,0 +1 @@ +obj-m += gregkh.o --- /dev/null +++ gregkh-2.6/drivers/gregkh/gregkh.c @@ -0,0 +1,311 @@ +/* + * greg kroah-hartman's junk module + * + * Copyright (C) 2004-2006 Greg Kroah-Hartman + * + * The place I use to mess around with new ideas... + * + * Released under the GPL V2 only. + * + * use at your own risk... + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define dbg(format, arg...) \ + printk(KERN_ERR "GREGKH: " format , ## arg) + +struct greg { + struct kobject kobj; + u32 a; + u16 b; + u8 c; + void * d; +}; + +struct d_greg { + u16 foo; + struct greg g; + u16 baz; +}; + +struct greg_attribute { + struct attribute attr; + u32 offset; + ssize_t (*show)(struct greg *, char * buf, u32 offset); + ssize_t (*store)(struct greg *, const char * buf, size_t count); +}; +#define to_greg_attr(_attr) container_of(_attr, struct greg_attribute, attr) +#define to_greg(obj) container_of(obj, struct greg, kobj) + +static ssize_t greg_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +{ + struct greg_attribute *g_attr = to_greg_attr(attr); + struct greg *g = to_greg(kobj); + ssize_t ret = 0; + + dbg("%s kobj=%p g=%p\n", __FUNCTION__, kobj, g); + if (g_attr->show) + ret = g_attr->show(g, buf, g_attr->offset); + return ret; +} + +static ssize_t greg_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) +{ + struct greg_attribute *g_attr = to_greg_attr(attr); + struct greg *g = to_greg(kobj); + ssize_t ret = 0; + + if (g_attr->store) + ret = g_attr->store(g, buf, count); + return ret; +} + +static struct sysfs_ops greg_sysfs_ops = { + .show = greg_attr_show, + .store = greg_attr_store, +}; + +static void greg_kobj_release(struct kobject *kobj) +{ + kfree(container_of(kobj, struct greg, kobj)); +} + +static struct kobj_type greg_ktype = { + .sysfs_ops = &greg_sysfs_ops, + .release = &greg_kobj_release, +}; + + +static decl_subsys(gregkh, &greg_ktype, NULL); + +static struct greg *g1; +static struct greg *g2; + +static ssize_t u32_show(struct greg *g, char *buf, u32 offset) +{ + void *v = g; + u32 *val = offset + v; + dbg("%s val=%p\n", __FUNCTION__, val); + return sprintf(buf, "%d\n", *val); +} + +static ssize_t u16_show(struct greg *g, char *buf, u32 offset) +{ + void *v = g; + u16 *val = offset + v; + dbg("%s val=%p\n", __FUNCTION__, val); + return sprintf(buf, "%d\n", *val); +} + +static ssize_t u8_show(struct greg *g, char *buf, u32 offset) +{ + void *v = g; + u8 *val = offset + v; + dbg("%s val=%p\n", __FUNCTION__, val); + return sprintf(buf, "%d\n", *val); +} + +static ssize_t void_ptr_show(struct greg *g, char *buf, u32 offset) +{ + void *v = g; + void **val = offset + v; + dbg("%s val=%p\n", __FUNCTION__, val); + return sprintf(buf, "%p\n", *val); +} + +#define to_d_greg(obj) container_of(obj, struct d_greg, g) + +#if 0 +/* we want the to figure out where baz is in memory, and we're given a struct greg *, + * so, how to get there... */ +static void x(struct greg *g) +{ + u16 *baz_pointer; + void *v; + struct d_greg *d; + s32 o1, o2; + + /* we can get from greg to a d_greg with container_of */ + d = to_d_greg(g); + v = d; + + /* now to the baz by adding the offset within d_greg */ + baz_pointer = v + offsetof(struct d_greg, baz); + + /* we got it, but let's do it in one line... */ + baz_pointer = ((void *)to_d_greg(g) + offsetof(struct d_greg, baz)); + + /* ok, put it in a #define for all to use... */ +#define find_it_1(container, offset) \ + ((void *)(container) + offset) + + baz_pointer = find_it_1(to_d_greg(g), offsetof(struct d_greg, baz)); + + /* simpler... */ +#define find_it_2(ptr, type, member, var) \ + ((void *)(container_of(ptr, type, member) + offsetof(type, var))) + baz_pointer = find_it_2(g, struct d_greg, g, baz); + + /* just numbers, no pointers */ + o1 = offsetof(struct d_greg, g); + o2 = offsetof(struct d_greg, baz); + v = g; + baz_pointer = v - o1 + o2; +} + +#define void_container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#define D_RO(_name, _ptr, +#endif + + +#define G_RO(_name, _var, _type) \ +static struct greg_attribute _name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \ + .offset = offsetof(struct greg, _var), \ + .show = _type##_show, \ +} + +G_RO(a, a, u32); +G_RO(b, b, u16); +G_RO(c, c, u8); +G_RO(d, d, void_ptr); + +static struct attribute * g_attrs[] = { + &a_attr.attr, + &b_attr.attr, + &c_attr.attr, + &d_attr.attr, + NULL +}; + +static struct attribute_group g_attr_group = { + .attrs = g_attrs, +}; + +#if 0 +#define G_ATTR_RO(_name) \ +static struct greg_attribute _name##_attr = __ATTR_RO(_name) + +#define G_ATTR_RW(_name) \ +static struct greg_attribute _name##_attr = \ + __ATTR(_name, 0644, _name##_show, _name##_store) + +static struct greg_attribute b_attr = { + .attr = {.name ="b", .mode =0444, .owner = THIS_MODULE }, + .show = b_show, +}; +//G_ATTR_RO(a); +//G_ATTR_RO(b); +#endif + +static struct class *greg_class; + + +ssize_t cd_show(struct class_device *cd, char *buf) +{ + return sprintf(buf, "this is device %s\n", kobject_name(&cd->kobj)); +} +static CLASS_DEVICE_ATTR(name, 0444, cd_show, NULL); + + + +static void greg_class_init(void) +{ + struct class_device *g2; + struct class_device *cd; + struct class_device *dup; + + greg_class = class_create(THIS_MODULE, "gregkh"); + + class_device_create(greg_class, NULL, MKDEV(42, 0), NULL, "greg1"); + g2 = class_device_create(greg_class, NULL, MKDEV(42, 1), NULL, "greg2"); + class_device_create(greg_class, NULL, MKDEV(42, 2), NULL, "greg3"); + + dbg("create a dupe name\n"); + dup = class_device_create(greg_class, NULL, MKDEV(42, 3), NULL, "greg1"); + dbg("dup name created, dup = %p\n", dup); + + class_device_create(greg_class, g2, MKDEV(42,4), NULL, "greg2.4"); + class_device_create(greg_class, g2, 0, NULL, "greg2.%s", "null"); + cd = class_device_create(greg_class, g2, MKDEV(42,5), NULL, "greg%d.%d", 2, 5); + class_device_create_file(cd, &class_device_attr_name); + +} + + +static int greg_init(void) +{ + int error; + + error = subsystem_register(&gregkh_subsys); + if (error) { + dbg("error %d\n", error); + return error; + } + + g1 = kmalloc(sizeof(*g1), GFP_KERNEL); + memset(g1, 0x00, sizeof(*g1)); + g1->a = 1; + g1->b = 2; + g1->c = 3; + g1->d = g1; + + g2 = kmalloc(sizeof(*g2), GFP_KERNEL); + memset(g2, 0x00, sizeof(*g2)); + g2->a = 1; + g2->b = 2; + g2->c = 3; + g2->d = g2; + + kobject_set_name(&g1->kobj, "g1"); + kobject_set_name(&g2->kobj, "g2"); + + kobj_set_kset_s(g1, gregkh_subsys); + kobj_set_kset_s(g2, gregkh_subsys); + g1->kobj.parent = &gregkh_subsys.kset.kobj; + g2->kobj.parent = &gregkh_subsys.kset.kobj; + + kobject_register(&g1->kobj); + kobject_register(&g2->kobj); + +// error = sysfs_create_file(&g1->kobj, &a_attr.attr); +// error = sysfs_create_file(&g2->kobj, &b_attr.attr); +// error = sysfs_create_file(&g2->kobj, &c_attr.attr); +// error = sysfs_create_file(&g2->kobj, &d_attr.attr); + error = sysfs_create_group(&g1->kobj, &g_attr_group); + error = sysfs_create_group(&g2->kobj, &g_attr_group); + dbg("%s g1=%p\n", __FUNCTION__, g1); + dbg("%s g2=%p\n", __FUNCTION__, g2); + + greg_class_init(); + + return error; +} + + +static void greg_exit(void) +{ + kobject_unregister(&g1->kobj); + kobject_unregister(&g2->kobj); + subsystem_unregister(&gregkh_subsys); + + class_destroy(greg_class); +} + + + + +module_init(greg_init); +module_exit(greg_exit); +MODULE_LICENSE("GPL");