aboutsummaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-06-14 16:51:12 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-14 16:51:12 -0700
commitcf45b5d4be20d0b0c235989c58ffd050051a3d48 (patch)
tree09e613963fddce5fdfa092a99a9b3a7eff7ec88a /driver
parente6b88ef30ffe1805ffd78a2b689e3f464577e63d (diff)
downloadpatches-cf45b5d4be20d0b0c235989c58ffd050051a3d48.tar.gz
move device-class patch to driver/ to get it to be picked up.
Also add endpoint patches as they are starting to work...
Diffstat (limited to 'driver')
-rw-r--r--driver/device-class.patch305
1 files changed, 305 insertions, 0 deletions
diff --git a/driver/device-class.patch b/driver/device-class.patch
new file mode 100644
index 0000000000000..bc86f1385c447
--- /dev/null
+++ b/driver/device-class.patch
@@ -0,0 +1,305 @@
+From foo@baz Tue Apr 9 12:12:43 2002
+Date: Wed, 14 Jun 2006 12:14:34 -0700
+To: Greg KH <greg@kroah.com>
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Driver core: allow struct device to have a dev_t
+
+This is the first step in moving class_device to being replaced by
+struct device. It allows struct device to export a dev_t and makes it
+easy to dynamically create and destroy struct device as long as they are
+associated with a specific class.
+
+Cc: Kay Sievers <kay.sievers@vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/base/class.c | 1
+ drivers/base/core.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/device.h | 14 ++++
+ 3 files changed, 176 insertions(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/base/class.c
++++ gregkh-2.6/drivers/base/class.c
+@@ -142,6 +142,7 @@ int class_register(struct class * cls)
+ pr_debug("device class '%s': registering\n", cls->name);
+
+ INIT_LIST_HEAD(&cls->children);
++ INIT_LIST_HEAD(&cls->devices);
+ INIT_LIST_HEAD(&cls->interfaces);
+ init_MUTEX(&cls->sem);
+ error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
+--- gregkh-2.6.orig/drivers/base/core.c
++++ gregkh-2.6/drivers/base/core.c
+@@ -15,6 +15,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
++#include <linux/kdev_t.h>
+
+ #include <asm/semaphore.h>
+
+@@ -98,6 +99,8 @@ static int dev_uevent_filter(struct kset
+ struct device *dev = to_dev(kobj);
+ if (dev->bus)
+ return 1;
++ if (dev->class)
++ return 1;
+ }
+ return 0;
+ }
+@@ -106,7 +109,11 @@ static const char *dev_uevent_name(struc
+ {
+ struct device *dev = to_dev(kobj);
+
+- return dev->bus->name;
++ if (dev->bus)
++ return dev->bus->name;
++ if (dev->class)
++ return dev->class->name;
++ return NULL;
+ }
+
+ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
+@@ -117,6 +124,19 @@ static int dev_uevent(struct kset *kset,
+ int length = 0;
+ int retval = 0;
+
++ /* add the major/minor if present */
++ if (dev->class) {
++ if (MAJOR(dev->devt)) {
++ add_uevent_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "MAJOR=%u", MAJOR(dev->devt));
++
++ add_uevent_var(envp, num_envp, &i,
++ buffer, buffer_size, &length,
++ "MINOR=%u", MINOR(dev->devt));
++ }
++ }
++
+ /* add bus name of physical device */
+ if (dev->bus)
+ add_uevent_var(envp, num_envp, &i,
+@@ -161,6 +181,12 @@ static ssize_t store_uevent(struct devic
+ return count;
+ }
+
++static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return print_dev_t(buf, dev->devt);
++}
++
+ /*
+ * devices_subsys - structure to be registered with kobject core.
+ */
+@@ -231,6 +257,7 @@ void device_initialize(struct device *de
+ klist_init(&dev->klist_children, klist_children_get,
+ klist_children_put);
+ INIT_LIST_HEAD(&dev->dma_pools);
++ INIT_LIST_HEAD(&dev->node);
+ init_MUTEX(&dev->sem);
+ device_init_wakeup(dev, 0);
+ }
+@@ -274,6 +301,26 @@ int device_add(struct device *dev)
+ dev->uevent_attr.store = store_uevent;
+ device_create_file(dev, &dev->uevent_attr);
+
++ if (MAJOR(dev->devt)) {
++ struct device_attribute *attr;
++ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
++ if (!attr) {
++ error = -ENOMEM;
++ goto PMError;
++ }
++ attr->attr.name = "dev";
++ attr->attr.mode = S_IRUGO;
++ if (dev->driver)
++ attr->attr.owner = dev->driver->owner;
++ attr->show = show_dev;
++ error = device_create_file(dev, attr);
++ if (error) {
++ kfree(attr);
++ goto attrError;
++ }
++
++ dev->devt_attr = attr;
++ }
+ if ((error = device_pm_add(dev)))
+ goto PMError;
+ if ((error = bus_add_device(dev)))
+@@ -292,6 +339,11 @@ int device_add(struct device *dev)
+ BusError:
+ device_pm_remove(dev);
+ PMError:
++ if (dev->devt_attr) {
++ device_remove_file(dev, dev->devt_attr);
++ kfree(dev->devt_attr);
++ }
++ attrError:
+ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+ kobject_del(&dev->kobj);
+ Error:
+@@ -367,6 +419,8 @@ void device_del(struct device * dev)
+
+ if (parent)
+ klist_del(&dev->knode_parent);
++ if (dev->devt_attr)
++ device_remove_file(dev, dev->devt_attr);
+ device_remove_file(dev, &dev->uevent_attr);
+
+ /* Notify the platform of the removal, in case they
+@@ -451,3 +505,109 @@ EXPORT_SYMBOL_GPL(put_device);
+
+ EXPORT_SYMBOL_GPL(device_create_file);
+ EXPORT_SYMBOL_GPL(device_remove_file);
++
++
++static void device_create_release(struct device *dev)
++{
++ pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id);
++ kfree(dev);
++}
++
++/**
++ * device_create - creates a device and registers it with sysfs
++ * @cs: pointer to the struct class that this device should be registered to.
++ * @parent: pointer to the parent struct device of this new device, if any.
++ * @dev: the dev_t for the char device to be added.
++ * @fmt: string for the class device's name
++ *
++ * This function can be used by char device classes. A struct
++ * device will be created in sysfs, registered to the specified
++ * class.
++ * A "dev" file will be created, showing the dev_t for the device, if
++ * the dev_t is not 0,0.
++ * If a pointer to a parent struct device is passed in, the newly
++ * created struct device will be a child of that device in sysfs. The
++ * pointer to the struct 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 device *device_create(struct class *class, struct device *parent,
++ dev_t devt, char *fmt, ...)
++{
++ va_list args;
++ struct device *dev = NULL;
++ int retval = -ENODEV;
++
++ if (class == NULL || IS_ERR(class))
++ goto error;
++ if (parent == NULL) {
++ printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__);
++ goto error;
++ }
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
++ dev->devt = devt;
++ dev->class = class;
++ dev->parent = parent;
++ dev->release = device_create_release;
++
++ va_start(args, fmt);
++ vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
++ va_end(args);
++ retval = device_register(dev);
++ if (retval)
++ goto error;
++
++ /* tie the class to the device */
++ down(&class->sem);
++ list_add_tail(&dev->node, &class->devices);
++ up(&class->sem);
++ sysfs_create_link(&class->subsys.kset.kobj, &dev->kobj, dev->bus_id);
++
++ return dev;
++
++error:
++ kfree(dev);
++ return ERR_PTR(retval);
++}
++EXPORT_SYMBOL_GPL(device_create);
++
++/**
++ * device_destroy - removes a device that was created with device_create()
++ * @class: 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 device_destroy(struct class *class, dev_t devt)
++{
++ struct device *dev = NULL;
++ struct device *dev_tmp;
++
++ down(&class->sem);
++ list_for_each_entry(dev_tmp, &class->devices, node) {
++ if (dev_tmp->devt == devt) {
++ dev = dev_tmp;
++ break;
++ }
++ }
++ up(&class->sem);
++
++ if (dev) {
++ sysfs_remove_link(&class->subsys.kset.kobj, dev->bus_id);
++ list_del_init(&dev->node);
++ device_unregister(dev);
++ }
++}
++EXPORT_SYMBOL_GPL(device_destroy);
++
++
+--- gregkh-2.6.orig/include/linux/device.h
++++ gregkh-2.6/include/linux/device.h
+@@ -143,6 +143,7 @@ struct class {
+
+ struct subsystem subsys;
+ struct list_head children;
++ struct list_head devices;
+ struct list_head interfaces;
+ struct semaphore sem; /* locks both the children and interfaces lists */
+
+@@ -306,6 +307,7 @@ struct device {
+ struct kobject kobj;
+ char bus_id[BUS_ID_SIZE]; /* position on parent bus */
+ struct device_attribute uevent_attr;
++ struct device_attribute *devt_attr;
+
+ struct semaphore sem; /* semaphore to synchronize calls to
+ * its driver.
+@@ -333,6 +335,11 @@ struct device {
+ struct dma_coherent_mem *dma_mem; /* internal for coherent mem
+ override */
+
++ /* class_device migration path */
++ struct list_head node;
++ struct class *class; /* optional*/
++ dev_t devt; /* dev_t, creates the sysfs "dev" */
++
+ void (*release)(struct device * dev);
+ };
+
+@@ -374,6 +381,13 @@ extern int device_attach(struct device
+ extern void driver_attach(struct device_driver * drv);
+ extern void device_reprobe(struct device *dev);
+
++/*
++ * Easy functions for dynamically creating devices on the fly
++ */
++extern struct device *device_create(struct class *cls, struct device *parent,
++ dev_t devt, char *fmt, ...)
++ __attribute__((format(printf,4,5)));
++extern void device_destroy(struct class *cls, dev_t devt);
+
+ /*
+ * Platform "fixup" functions - allow the platform to have their say