]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/base/core.c
driver-core: prepare for 2.6.27 api change by adding dev_set_name
[linux-2.6-omap-h63xx.git] / drivers / base / core.c
index 24198ad0197654943ae95250b22386358cb22e71..422cfcad486d3eab10b79318caaed63997b93a24 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/notifier.h>
 #include <linux/genhd.h>
 #include <linux/kallsyms.h>
-#include <asm/semaphore.h>
+#include <linux/semaphore.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -207,7 +207,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
                retval = dev->bus->uevent(dev, env);
                if (retval)
                        pr_debug("device: '%s': %s: bus uevent() returned %d\n",
-                                dev->bus_id, __FUNCTION__, retval);
+                                dev->bus_id, __func__, retval);
        }
 
        /* have the class specific function add its stuff */
@@ -216,7 +216,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
                if (retval)
                        pr_debug("device: '%s': %s: class uevent() "
                                 "returned %d\n", dev->bus_id,
-                                __FUNCTION__, retval);
+                                __func__, retval);
        }
 
        /* have the device type specific fuction add its stuff */
@@ -225,7 +225,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
                if (retval)
                        pr_debug("device: '%s': %s: dev_type uevent() "
                                 "returned %d\n", dev->bus_id,
-                                __FUNCTION__, retval);
+                                __func__, retval);
        }
 
        return retval;
@@ -759,6 +759,21 @@ static void device_remove_class_symlinks(struct device *dev)
        sysfs_remove_link(&dev->kobj, "subsystem");
 }
 
+/**
+ * dev_set_name - set a device name
+ * @dev: device
+ */
+int dev_set_name(struct device *dev, const char *fmt, ...)
+{
+       va_list vargs;
+
+       va_start(vargs, fmt);
+       vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
+       va_end(vargs);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dev_set_name);
+
 /**
  * device_add - add device to device hierarchy.
  * @dev: device.
@@ -782,11 +797,15 @@ int device_add(struct device *dev)
                goto Done;
        }
 
-       pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+       pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
 
        parent = get_device(dev->parent);
        setup_parent(dev, parent);
 
+       /* use parent numa_node */
+       if (parent)
+               set_dev_node(dev, dev_to_node(parent));
+
        /* first, register with generic layer. */
        error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
        if (error)
@@ -817,13 +836,12 @@ int device_add(struct device *dev)
        error = device_add_attrs(dev);
        if (error)
                goto AttrsError;
-       error = dpm_sysfs_add(dev);
-       if (error)
-               goto PMError;
-       device_pm_add(dev);
        error = bus_add_device(dev);
        if (error)
                goto BusError;
+       error = device_pm_add(dev);
+       if (error)
+               goto PMError;
        kobject_uevent(&dev->kobj, KOBJ_ADD);
        bus_attach_device(dev);
        if (parent)
@@ -843,9 +861,9 @@ int device_add(struct device *dev)
  Done:
        put_device(dev);
        return error;
- BusError:
-       device_pm_remove(dev);
  PMError:
+       bus_remove_device(dev);
+ BusError:
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DEL_DEVICE, dev);
@@ -981,7 +999,7 @@ void device_del(struct device *dev)
  */
 void device_unregister(struct device *dev)
 {
-       pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+       pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
        device_del(dev);
        put_device(dev);
 }
@@ -1076,16 +1094,18 @@ EXPORT_SYMBOL_GPL(device_remove_file);
 
 static void device_create_release(struct device *dev)
 {
-       pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+       pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
        kfree(dev);
 }
 
 /**
- * device_create - creates a device and registers it with sysfs
+ * device_create_vargs - creates a device and registers it with sysfs
  * @class: 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
  * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
  * @fmt: string for the device's name
+ * @args: va_list for the 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.
@@ -1101,10 +1121,10 @@ static void device_create_release(struct device *dev)
  * 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, const char *fmt, ...)
+struct device *device_create_vargs(struct class *class, struct device *parent,
+                                  dev_t devt, void *drvdata, const char *fmt,
+                                  va_list args)
 {
-       va_list args;
        struct device *dev = NULL;
        int retval = -ENODEV;
 
@@ -1121,10 +1141,9 @@ struct device *device_create(struct class *class, struct device *parent,
        dev->class = class;
        dev->parent = parent;
        dev->release = device_create_release;
+       dev_set_drvdata(dev, drvdata);
 
-       va_start(args, fmt);
        vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
-       va_end(args);
        retval = device_register(dev);
        if (retval)
                goto error;
@@ -1135,6 +1154,78 @@ error:
        kfree(dev);
        return ERR_PTR(retval);
 }
+EXPORT_SYMBOL_GPL(device_create_vargs);
+
+/**
+ * device_create_drvdata - creates a device and registers it with sysfs
+ * @class: 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
+ * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
+ * @fmt: string for the 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_drvdata(struct class *class,
+                                    struct device *parent,
+                                    dev_t devt,
+                                    void *drvdata,
+                                    const char *fmt, ...)
+{
+       va_list vargs;
+       struct device *dev;
+
+       va_start(vargs, fmt);
+       dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
+       va_end(vargs);
+       return dev;
+}
+EXPORT_SYMBOL_GPL(device_create_drvdata);
+
+/**
+ * device_create - creates a device and registers it with sysfs
+ * @class: 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
+ * @devt: the dev_t for the char device to be added
+ * @fmt: string for the 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, const char *fmt, ...)
+{
+       va_list vargs;
+       struct device *dev;
+
+       va_start(vargs, fmt);
+       dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
+       va_end(vargs);
+       return dev;
+}
 EXPORT_SYMBOL_GPL(device_create);
 
 static int __match_devt(struct device *dev, void *data)
@@ -1164,35 +1255,6 @@ void device_destroy(struct class *class, dev_t devt)
 }
 EXPORT_SYMBOL_GPL(device_destroy);
 
-#ifdef CONFIG_PM_SLEEP
-/**
- * destroy_suspended_device - asks the PM core to remove a suspended device
- * @class: pointer to the struct class that this device was registered with
- * @devt: the dev_t of the device that was previously registered
- *
- * This call notifies the PM core of the necessity to unregister a suspended
- * device created with a call to device_create() (devices cannot be
- * unregistered directly while suspended, since the PM core holds their
- * semaphores at that time).
- *
- * It can only be called within the scope of a system sleep transition.  In
- * practice this means it has to be directly or indirectly invoked either by
- * a suspend or resume method, or by the PM core (e.g. via
- * disable_nonboot_cpus() or enable_nonboot_cpus()).
- */
-void destroy_suspended_device(struct class *class, dev_t devt)
-{
-       struct device *dev;
-
-       dev = class_find_device(class, &devt, __match_devt);
-       if (dev) {
-               device_pm_schedule_removal(dev);
-               put_device(dev);
-       }
-}
-EXPORT_SYMBOL_GPL(destroy_suspended_device);
-#endif /* CONFIG_PM_SLEEP */
-
 /**
  * device_rename - renames a device
  * @dev: the pointer to the struct device to be renamed
@@ -1210,7 +1272,7 @@ int device_rename(struct device *dev, char *new_name)
                return -EINVAL;
 
        pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
-                __FUNCTION__, new_name);
+                __func__, new_name);
 
 #ifdef CONFIG_SYSFS_DEPRECATED
        if ((dev->class) && (dev->parent))
@@ -1244,13 +1306,11 @@ int device_rename(struct device *dev, char *new_name)
        }
 #else
        if (dev->class) {
-               sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
                error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
                                          dev->bus_id);
-               if (error) {
-                       dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
-                               __FUNCTION__, error);
-               }
+               if (error)
+                       goto out;
+               sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
        }
 #endif
 
@@ -1325,7 +1385,7 @@ int device_move(struct device *dev, struct device *new_parent)
        new_parent_kobj = get_device_parent(dev, new_parent);
 
        pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
-                __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
+                __func__, new_parent ? new_parent->bus_id : "<NULL>");
        error = kobject_move(&dev->kobj, new_parent_kobj);
        if (error) {
                cleanup_glue_dir(dev, new_parent_kobj);
@@ -1336,8 +1396,11 @@ int device_move(struct device *dev, struct device *new_parent)
        dev->parent = new_parent;
        if (old_parent)
                klist_remove(&dev->knode_parent);
-       if (new_parent)
+       if (new_parent) {
                klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+               set_dev_node(dev, dev_to_node(new_parent));
+       }
+
        if (!dev->class)
                goto out_put;
        error = device_move_class_links(dev, old_parent, new_parent);
@@ -1347,9 +1410,12 @@ int device_move(struct device *dev, struct device *new_parent)
                if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
                        if (new_parent)
                                klist_remove(&dev->knode_parent);
-                       if (old_parent)
+                       dev->parent = old_parent;
+                       if (old_parent) {
                                klist_add_tail(&dev->knode_parent,
                                               &old_parent->klist_children);
+                               set_dev_node(dev, dev_to_node(old_parent));
+                       }
                }
                cleanup_glue_dir(dev, new_parent_kobj);
                put_device(new_parent);