aboutsummaryrefslogtreecommitdiffstats
path: root/bad
diff options
context:
space:
mode:
authorGreg KH <greg@press.(none)>2005-10-18 11:29:14 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-18 11:29:14 -0700
commit3ff4d78b5ca6701ee5056bc177602bd8b571b760 (patch)
tree0dc21d2d05e8768a569c06a7217dcbac655bb210 /bad
parent1ba0debc2902c1ccdaef8db09725f8eb47aad496 (diff)
downloadpatches-3ff4d78b5ca6701ee5056bc177602bd8b571b760.tar.gz
lots of i2c patches.
created the bad/ directory for stuff that's not worth applying, but not bad enough to throw away.
Diffstat (limited to 'bad')
-rw-r--r--bad/README5
-rw-r--r--bad/subclass.patch754
2 files changed, 759 insertions, 0 deletions
diff --git a/bad/README b/bad/README
new file mode 100644
index 0000000000000..63ab6bd33bf2f
--- /dev/null
+++ b/bad/README
@@ -0,0 +1,5 @@
+stuff in here was just a bad idea, or didn't work out.
+Instead of just throwing them away, I'm keeping them here incase I need them
+in the future.
+
+Yeah, I'm a pack-rat with patches just like in real life...
diff --git a/bad/subclass.patch b/bad/subclass.patch
new file mode 100644
index 0000000000000..91186d65abc91
--- /dev/null
+++ b/bad/subclass.patch
@@ -0,0 +1,754 @@
+ drivers/base/Makefile | 2
+ drivers/base/base.h | 2
+ drivers/base/class.c | 3
+ drivers/base/subclass.c | 569 ++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/gregkh.c | 20 +
+ include/linux/device.h | 66 +++++
+ 6 files changed, 659 insertions(+), 3 deletions(-)
+
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gregkh-2.6/drivers/base/subclass.c 2005-09-26 16:12:20.000000000 -0700
+@@ -0,0 +1,569 @@
++/*
++ * subclass.c - subclass crap
++ *
++ * Portions based on drivers/base/class.c, which is:
++ * Copyright (c) 2002-3 Patrick Mochel
++ * Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2003-2004 Greg Kroah-Hartman
++ * Copyright (c) 2003-2004 IBM Corp.
++ *
++ * Copyright (c) 2005 Greg Kroah-Hartman
++ * Copyright (c) 2005 Novell, Inc.
++ *
++ * This file is released under the GPLv2
++ */
++
++#include <linux/config.h>
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/kdev_t.h>
++#include <linux/err.h>
++#include <linux/ndevfs.h>
++#include "base.h"
++
++#define to_subclass_attr(_attr) container_of(_attr, struct subclass_attribute, attr)
++#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
++
++
++int subclass_device_create_file(struct subclass_device *dev,
++ const struct subclass_device_attribute *attr)
++{
++ int error = -EINVAL;
++ if (dev)
++ error = sysfs_create_file(&dev->kobj, &attr->attr);
++ return error;
++}
++EXPORT_SYMBOL_GPL(subclass_device_create_file);
++
++void subclass_device_remove_file(struct subclass_device *dev,
++ const struct subclass_device_attribute *attr)
++{
++ if (dev)
++ sysfs_remove_file(&dev->kobj, &attr->attr);
++}
++EXPORT_SYMBOL_GPL(subclass_device_remove_file);
++
++int subclass_device_create_bin_file(struct subclass_device *dev,
++ struct bin_attribute *attr)
++{
++ int error = -EINVAL;
++ if (dev)
++ error = sysfs_create_bin_file(&dev->kobj, attr);
++ return error;
++}
++
++void subclass_device_remove_bin_file(struct subclass_device *dev,
++ struct bin_attribute *attr)
++{
++ if (dev)
++ sysfs_remove_bin_file(&dev->kobj, attr);
++}
++
++static inline struct subclass_device *to_subclass_dev(struct kobject *obj)
++{
++ return container_of(obj, struct subclass_device, kobj);
++}
++
++static inline struct subclass_device_attribute *to_subclass_dev_attr(struct attribute *_attr)
++{
++ return container_of(_attr, struct subclass_device_attribute, attr);
++}
++
++
++static ssize_t subclass_device_attr_show(struct kobject *kobj, struct attribute *attr,
++ char * buf)
++{
++ struct subclass_device_attribute *dev_attr = to_subclass_dev_attr(attr);
++ struct subclass_device *dev = to_subclass_dev(kobj);
++ ssize_t ret = 0;
++
++ if (dev_attr->show)
++ ret = dev_attr->show(dev, dev_attr, buf);
++ return ret;
++}
++
++static ssize_t subclass_device_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t count)
++{
++ struct subclass_device_attribute *dev_attr = to_subclass_dev_attr(attr);
++ struct subclass_device *dev = to_subclass_dev(kobj);
++ ssize_t ret = 0;
++
++ if (dev_attr->store)
++ ret = dev_attr->store(dev, dev_attr, buf, count);
++ return ret;
++}
++
++static struct sysfs_ops subclass_dev_sysfs_ops = {
++ .show = subclass_device_attr_show,
++ .store = subclass_device_attr_store,
++};
++
++static void subclass_dev_release(struct kobject *kobj)
++{
++ struct subclass_device *sd = to_subclass_dev(kobj);
++ struct class_device *class_dev = sd->parent;
++
++ pr_debug("subclass device '%s': release.\n", kobject_name(&sd->kobj));
++
++ kfree(sd->devt_attr);
++ sd->devt_attr = NULL;
++
++ if (class_dev->release)
++ class_dev->release(sd);
++ else {
++ printk(KERN_ERR "Class Device '%s' does not have a release() function, "
++ "it is broken and must be fixed.\n",
++ class_dev->class_id);
++ WARN_ON(1);
++ }
++}
++
++static struct kobj_type ktype_subclass_device = {
++ .sysfs_ops = &subclass_dev_sysfs_ops,
++ .release = subclass_dev_release,
++};
++
++static int subclass_hotplug_filter(struct kset *kset, struct kobject *kobj)
++{
++ struct kobj_type *ktype = get_ktype(kobj);
++
++ if (ktype == &ktype_subclass_device) {
++ struct subclass_device *dev = to_subclass_dev(kobj);
++ if (dev->parent)
++ return 1;
++ }
++ return 0;
++}
++
++static const char *subclass_hotplug_name(struct kset *kset, struct kobject *kobj)
++{
++ struct subclass_device *dev = to_subclass_dev(kobj);
++
++ return dev->parent->class->name;
++}
++
++static int subclass_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
++ int num_envp, char *buffer, int buffer_size)
++{
++ struct subclass_device *sd = to_subclass_dev(kobj);
++ int i = 0;
++ int length = 0;
++ int retval = 0;
++
++ pr_debug("%s - name = %s\n", __FUNCTION__, kobject_name(&sd->kobj));
++
++ if (sd->dev) {
++ /* add physical device, backing this device */
++ struct device *dev = sd->dev;
++ char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
++
++ add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
++ &length, "PHYSDEVPATH=%s", path);
++ kfree(path);
++
++ if (dev->bus)
++ add_hotplug_env_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "PHYSDEVBUS=%s", dev->bus->name);
++
++ if (dev->driver)
++ add_hotplug_env_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "PHYSDEVDRIVER=%s", dev->driver->name);
++ }
++
++ if (MAJOR(sd->devt)) {
++ add_hotplug_env_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "MAJOR=%u", MAJOR(sd->devt));
++
++ add_hotplug_env_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "MINOR=%u", MINOR(sd->devt));
++ }
++
++ /* terminate, set to next free slot, shrink available space */
++ envp[i] = NULL;
++ envp = &envp[i];
++ num_envp -= i;
++ buffer = &buffer[length];
++ buffer_size -= length;
++
++ if (sd->parent->class->hotplug) {
++ /* have the bus specific function add its stuff */
++ retval = sd->parent->class->hotplug(sd->parent, envp, num_envp,
++ buffer, buffer_size);
++ if (retval) {
++ pr_debug ("%s - hotplug() returned %d\n",
++ __FUNCTION__, retval);
++ }
++ }
++
++ return retval;
++}
++
++static struct kset_hotplug_ops subclass_hotplug_ops = {
++ .filter = subclass_hotplug_filter,
++ .name = subclass_hotplug_name,
++ .hotplug = subclass_hotplug,
++};
++
++static decl_subsys(subclass_obj, &ktype_subclass_device, &subclass_hotplug_ops);
++
++
++static int subclass_device_add_attrs(struct subclass_device *sd)
++{
++ int i;
++ int error = 0;
++ struct class *class = sd->parent->class;
++
++ if (class->subclass_dev_attrs) {
++ for (i = 0; attr_name(class->subclass_dev_attrs[i]); i++) {
++ error = subclass_device_create_file(sd,
++ &class->subclass_dev_attrs[i]);
++ if (error)
++ goto error;
++ }
++ }
++done:
++ return error;
++error:
++ while (--i >= 0)
++ subclass_device_remove_file(sd, &class->subclass_dev_attrs[i]);
++ goto done;
++}
++
++static void subclass_device_remove_attrs(struct subclass_device *sd)
++{
++ int i;
++ struct class *class = sd->parent->class;
++
++ if (class->subclass_dev_attrs) {
++ for (i = 0; attr_name(class->subclass_dev_attrs[i]); i++)
++ subclass_device_remove_file(sd, &class->subclass_dev_attrs[i]);
++ }
++}
++
++static ssize_t show_dev(struct subclass_device *sd,
++ struct subclass_device_attribute *attr, char *buf)
++{
++ return print_dev_t(buf, sd->devt);
++}
++
++static ssize_t show_sample(struct subclass_device *sd,
++ struct subclass_device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "#!/bin/sh\nmknod /dev/%s c %d %d\n",
++ kobject_name(&sd->kobj),
++ MAJOR(sd->devt), MINOR(sd->devt));
++}
++
++void subclass_device_initialize(struct subclass_device *sd)
++{
++ kobj_set_kset_s(sd, subclass_obj_subsys);
++ kobject_init(&sd->kobj);
++ INIT_LIST_HEAD(&sd->node);
++}
++
++static char *make_class_name(struct subclass_device *sd)
++{
++ char *name;
++ int size;
++
++ size = strlen(sd->parent->class->name) +
++ strlen(kobject_name(&sd->kobj)) + 2;
++
++ name = kmalloc(size, GFP_KERNEL);
++ if (!name)
++ return ERR_PTR(-ENOMEM);
++
++ strcpy(name, sd->parent->class->name);
++ strcat(name, ":");
++ strcat(name, kobject_name(&sd->kobj));
++ return name;
++}
++
++int subclass_device_add(struct subclass_device *sd)
++{
++ struct class_device *parent = NULL;
++ struct class_interface * class_intf;
++ char *class_name = NULL;
++ int error;
++
++ sd = subclass_device_get(sd);
++ if (!sd)
++ return -EINVAL;
++
++ if (!strlen(sd->class_id)) {
++ error = -EINVAL;
++ goto register_done;
++ }
++
++ parent = class_device_get(sd->parent);
++ if (!parent) {
++ error = -EINVAL;
++ goto register_done;
++ }
++
++ pr_debug("SUBCLASS: registering subclass device: '%s'\n", sd->class_id);
++
++ /* first, register with generic layer. */
++ kobject_set_name(&sd->kobj, "%s", sd->class_id);
++ if (parent)
++ sd->kobj.parent = &parent->kobj;
++
++ error = kobject_add(&sd->kobj);
++ if (error)
++ goto register_done;
++
++ /* add the needed attributes to this device */
++ if (MAJOR(sd->devt)) {
++ struct subclass_device_attribute *attr;
++ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
++ if (!attr) {
++ error = -ENOMEM;
++ kobject_del(&sd->kobj);
++ goto register_done;
++ }
++
++ attr->attr.name = "dev";
++ attr->attr.mode = S_IRUGO;
++ attr->attr.owner = parent->class->owner;
++ attr->show = show_dev;
++ attr->store = NULL;
++ subclass_device_create_file(sd, attr);
++ sd->devt_attr = attr;
++
++ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
++ if (!attr) {
++ error = -ENOMEM;
++ kobject_del(&sd->kobj);
++ goto register_done;
++ }
++ attr->attr.name = "sample.sh";
++ attr->attr.mode = S_IRUSR | S_IXUSR | S_IRUGO;
++ attr->attr.owner = parent->class->owner;
++ attr->show = show_sample;
++ attr->store = NULL;
++ subclass_device_create_file(sd, attr);
++ sd->sample_attr = attr;
++
++ ndevfs_create(kobject_name(&sd->kobj), sd->devt, 1);
++ }
++
++ subclass_device_add_attrs(sd);
++ if (sd->dev) {
++ class_name = make_class_name(sd);
++ sysfs_create_link(&sd->kobj, &sd->dev->kobj, "device");
++ sysfs_create_link(&sd->dev->kobj, &sd->kobj, class_name);
++ }
++
++ /* notify any interfaces this device is now here */
++ if (parent) {
++ down(&parent->sem);
++ list_add_tail(&sd->node, &parent->subdevs);
++// list_for_each_entry(class_intf, &parent->interfaces, node)
++// if (class_intf->add)
++// class_intf->add(class_dev);
++ up(&parent->sem);
++ }
++
++ kobject_hotplug(&sd->kobj, KOBJ_ADD);
++
++ register_done:
++ if (error && parent)
++ class_device_put(parent);
++ subclass_device_put(sd);
++ kfree(class_name);
++ return error;
++}
++
++int subclass_device_register(struct subclass_device *sd)
++{
++ subclass_device_initialize(sd);
++ return subclass_device_add(sd);
++}
++
++/**
++ * class_device_create - creates a class device and registers it with sysfs
++ * @cs: pointer to the struct class that this device should be registered to.
++ * @dev: the dev_t for the char device to be added.
++ * @device: a pointer to a struct device that is assiociated with this class device.
++ * @fmt: string for the class device's name
++ *
++ * This function can be used by char device classes. A struct
++ * class_device will be created in sysfs, registered to the specified
++ * class. A "dev" file will be created, showing the dev_t for the
++ * device. The pointer to the struct class_device will be returned from
++ * the call. Any further sysfs files that might be required can be
++ * created using this pointer.
++ *
++ * Note: the struct class passed to this function must have previously
++ * been created with a call to class_create().
++ */
++struct subclass_device *subclass_device_create(struct class_device *class_dev,
++ dev_t devt, struct device *device,
++ char *fmt, ...)
++{
++ va_list args;
++ struct subclass_device *sd = NULL;
++ int retval = -ENODEV;
++
++ if (class_dev == NULL || IS_ERR(class_dev))
++ goto error;
++
++ sd = kzalloc(sizeof(struct subclass_device), GFP_KERNEL);
++ if (!sd) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
++ sd->devt = devt;
++ sd->dev = device;
++ sd->parent = class_dev;
++ sd->kobj.parent = &class_dev->kobj;
++
++ va_start(args, fmt);
++ vsnprintf(sd->class_id, BUS_ID_SIZE, fmt, args);
++ va_end(args);
++ retval = subclass_device_register(sd);
++ if (retval)
++ goto error;
++
++ return sd;
++
++error:
++ kfree(sd);
++ return ERR_PTR(retval);
++}
++EXPORT_SYMBOL_GPL(subclass_device_create);
++
++void subclass_device_del(struct subclass_device *sd)
++{
++ struct class_device *parent = sd->parent;
++ struct class_interface * class_intf;
++ char *class_name = NULL;
++
++ if (parent) {
++ down(&parent->sem);
++ list_del_init(&sd->node);
++// list_for_each_entry(class_intf, &parent->interfaces, node)
++// if (class_intf->remove)
++// class_intf->remove(class_dev);
++ up(&parent->sem);
++ }
++
++ if (sd->dev) {
++ class_name = make_class_name(sd);
++ sysfs_remove_link(&sd->kobj, "device");
++ sysfs_remove_link(&sd->dev->kobj, class_name);
++ }
++ if (sd->devt_attr) {
++ subclass_device_remove_file(sd, sd->devt_attr);
++ subclass_device_remove_file(sd, sd->sample_attr);
++ ndevfs_remove(kobject_name(&sd->kobj));
++ }
++ subclass_device_remove_attrs(sd);
++
++ kobject_hotplug(&sd->kobj, KOBJ_REMOVE);
++ kobject_del(&sd->kobj);
++
++ if (parent)
++ class_device_put(parent);
++ kfree(class_name);
++}
++
++void subclass_device_unregister(struct subclass_device *sd)
++{
++ pr_debug("SUBCLASS: Unregistering subclass device. ID = '%s'\n",
++ kobject_name(&sd->kobj));
++ subclass_device_del(sd);
++ subclass_device_put(sd);
++}
++
++/**
++ * subclass_device_destroy - removes a class device that was created with class_device_create()
++ * @cls: the pointer to the struct class that this device was registered * with.
++ * @dev: the dev_t of the device that was previously registered.
++ *
++ * This call unregisters and cleans up a class device that was created with a
++ * call to class_device_create()
++ */
++void subclass_device_destroy(struct class_device *class_dev, dev_t devt)
++{
++ struct subclass_device *sd = NULL;
++ struct subclass_device *sd_tmp;
++
++ down(&class_dev->sem);
++ list_for_each_entry(sd_tmp, &class_dev->subdevs, node) {
++ if (sd_tmp->devt == devt) {
++ sd = sd_tmp;
++ break;
++ }
++ }
++ up(&class_dev->sem);
++
++ if (sd)
++ subclass_device_unregister(sd);
++}
++EXPORT_SYMBOL_GPL(subclass_device_destroy);
++
++int subclass_device_rename(struct subclass_device *sd, char *new_name)
++{
++ int error = 0;
++ char *old_class_name = NULL, *new_class_name = NULL;
++
++ sd = subclass_device_get(sd);
++ if (!sd)
++ return -EINVAL;
++
++ pr_debug("SUBCLASS: renaming '%s' to '%s'\n", sd->class_id,
++ new_name);
++
++ if (sd->dev)
++ old_class_name = make_class_name(sd);
++
++ strlcpy(sd->class_id, new_name, KOBJ_NAME_LEN);
++
++ error = kobject_rename(&sd->kobj, new_name);
++
++ if (sd->dev) {
++ new_class_name = make_class_name(sd);
++ sysfs_create_link(&sd->dev->kobj, &sd->kobj, new_class_name);
++ sysfs_remove_link(&sd->dev->kobj, old_class_name);
++ }
++ subclass_device_put(sd);
++
++ kfree(old_class_name);
++ kfree(new_class_name);
++
++ return error;
++}
++
++struct subclass_device *subclass_device_get(struct subclass_device *sd)
++{
++ if (sd)
++ return to_subclass_dev(kobject_get(&sd->kobj));
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(subclass_device_get);
++
++void subclass_device_put(struct subclass_device *sd)
++{
++ kobject_put(&sd->kobj);
++}
++EXPORT_SYMBOL_GPL(subclass_device_put);
++
++void __init subclass_init(void)
++{
++ /* ick, this is ugly, the things we go through to keep from showing up
++ * in sysfs... */
++ subsystem_init(&subclass_obj_subsys);
++ if (!subclass_obj_subsys.kset.subsys)
++ subclass_obj_subsys.kset.subsys = &subclass_obj_subsys;
++}
++
++
+--- gregkh-2.6.orig/drivers/base/Makefile 2005-09-26 14:59:33.000000000 -0700
++++ gregkh-2.6/drivers/base/Makefile 2005-09-26 16:12:20.000000000 -0700
+@@ -1,7 +1,7 @@
+ # Makefile for the Linux device tree
+
+ obj-y := core.o sys.o bus.o dd.o \
+- driver.o class.o platform.o \
++ driver.o class.o subclass.o platform.o \
+ cpu.o firmware.o init.o map.o dmapool.o \
+ attribute_container.o transport_class.o
+ obj-y += power/
+--- gregkh-2.6.orig/include/linux/device.h 2005-09-26 14:59:33.000000000 -0700
++++ gregkh-2.6/include/linux/device.h 2005-09-26 16:12:20.000000000 -0700
+@@ -45,6 +45,7 @@
+ struct device_driver;
+ struct class;
+ struct class_device;
++struct subclass_device;
+
+ struct bus_type {
+ const char * name;
+@@ -163,6 +164,7 @@
+
+ struct class_attribute * class_attrs;
+ struct class_device_attribute * class_dev_attrs;
++ struct subclass_device_attribute* subclass_dev_attrs;
+
+ int (*hotplug)(struct class_device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
+@@ -201,7 +203,10 @@
+ struct class_device_attribute *sample_attr;
+ struct device * dev; /* not necessary, but nice to have */
+ void * class_data; /* class-specific data */
++ struct list_head subdevs;
++ struct semaphore sem; /* locks the subdevs list */
+
++ void (*release)(struct subclass_device *dev);
+ char class_id[BUS_ID_SIZE]; /* unique to this class */
+ };
+
+@@ -266,6 +271,67 @@
+ __attribute__((format(printf,4,5)));
+ extern void class_device_destroy(struct class *cls, dev_t devt);
+
++struct subclass_device {
++ struct list_head node;
++
++ struct kobject kobj;
++ struct class_device *parent; /* required */
++ struct device *dev; /* not necessary, but nice to have */
++ dev_t devt; /* dev_t, creates the sysfs "dev" */
++ struct subclass_device_attribute *devt_attr;
++ struct subclass_device_attribute *sample_attr;
++ char class_id[BUS_ID_SIZE]; /* unique to this class device */
++ void *data; /* class-specific data */
++};
++
++static inline void *subclass_get_devdata(struct subclass_device *dev)
++{
++ return dev->data;
++}
++
++static inline void subclass_set_devdata(struct subclass_device *dev, void *data)
++{
++ dev->data = data;
++}
++
++extern int subclass_device_register(struct subclass_device *);
++extern void subclass_device_unregister(struct subclass_device *);
++extern void subclass_device_initialize(struct subclass_device *);
++extern int subclass_device_add(struct subclass_device *);
++extern void subclass_device_del(struct subclass_device *);
++
++extern struct subclass_device *subclass_device_get(struct subclass_device *);
++extern void subclass_device_put(struct subclass_device *);
++
++struct subclass_device_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct subclass_device *,
++ struct subclass_device_attribute *attr, char *buf);
++ ssize_t (*store)(struct subclass_device *,
++ struct subclass_device_attribute *attr,
++ const char *buf, size_t count);
++};
++
++#define SUBCLASS_DEVICE_ATTR(_name,_mode,_show,_store) \
++struct subclass_device_attribute class_device_attr_##_name = \
++ __ATTR(_name,_mode,_show,_store)
++
++extern int subclass_device_create_file(struct subclass_device *,
++ const struct subclass_device_attribute *);
++extern void subclass_device_remove_file(struct subclass_device *,
++ const struct subclass_device_attribute *);
++extern int subclass_device_create_bin_file(struct subclass_device *,
++ struct bin_attribute *);
++extern void subclass_device_remove_bin_file(struct subclass_device *,
++ struct bin_attribute *);
++
++extern struct subclass_device *subclass_device_create(struct class_device *class_dev,
++ dev_t devt, struct device *device,
++ char *fmt, ...)
++ __attribute__((format(printf,4,5)));
++extern void subclass_device_destroy(struct class_device *class_dev, dev_t devt);
++
++
+
+ struct device {
+ struct klist klist_children;
+--- gregkh-2.6.orig/drivers/base/class.c 2005-09-26 14:59:33.000000000 -0700
++++ gregkh-2.6/drivers/base/class.c 2005-09-26 16:12:20.000000000 -0700
+@@ -455,6 +455,8 @@
+ kobj_set_kset_s(class_dev, class_obj_subsys);
+ kobject_init(&class_dev->kobj);
+ INIT_LIST_HEAD(&class_dev->node);
++ INIT_LIST_HEAD(&class_dev->subdevs);
++ init_MUTEX(&class_dev->sem);
+ }
+
+ static char *make_class_name(struct class_device *class_dev)
+@@ -797,6 +799,7 @@
+ subsystem_init(&class_obj_subsys);
+ if (!class_obj_subsys.kset.subsys)
+ class_obj_subsys.kset.subsys = &class_obj_subsys;
++ subclass_init();
+ return 0;
+ }
+
+--- gregkh-2.6.orig/drivers/usb/gregkh.c 2005-09-26 14:59:33.000000000 -0700
++++ gregkh-2.6/drivers/usb/gregkh.c 2005-09-26 16:12:20.000000000 -0700
+@@ -208,17 +208,35 @@
+
+ static struct class *greg_class;
+
++
++ssize_t sg_show(struct subclass_device *sd, struct subclass_device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "this is device %s\n", kobject_name(&sd->kobj));
++}
++static SUBCLASS_DEVICE_ATTR(name, 0444, sg_show, NULL);
++
++
++
+ static void greg_class_init(void)
+ {
++ struct class_device *g2;
++ struct subclass_device *sg;
++
+ greg_class = class_create(THIS_MODULE, "gregkh");
+
+ class_device_create(greg_class, MKDEV(42, 0), NULL, "greg1");
+- class_device_create(greg_class, MKDEV(42, 1), NULL, "greg2");
++ g2 = class_device_create(greg_class, MKDEV(42, 1), NULL, "greg2");
+ class_device_create(greg_class, MKDEV(42, 2), NULL, "greg3");
+
+ printk("GREG: create a dupe name\n");
+ class_device_create(greg_class, MKDEV(42, 3), NULL, "greg1");
+ printk("GREG: dup name created\n");
++
++ subclass_device_create(g2, MKDEV(42,4), NULL, "greg2.4");
++ subclass_device_create(g2, 0, NULL, "greg2.%s", "null");
++ sg = subclass_device_create(g2, MKDEV(42,5), NULL, "greg%d.%d", 2, 5);
++ subclass_device_create_file(sg, &class_device_attr_name);
++
+ }
+
+
+--- gregkh-2.6.orig/drivers/base/base.h 2005-09-26 14:59:33.000000000 -0700
++++ gregkh-2.6/drivers/base/base.h 2005-09-26 16:12:20.000000000 -0700
+@@ -18,4 +18,4 @@
+ return container_of(_attr, struct class_device_attribute, attr);
+ }
+
+-
++extern void subclass_init(void);