atomic: use <linux/atomic.h>
[linux-2.6.git] / include / linux / device.h
index a701c1b..c20dfbf 100644 (file)
@@ -2,7 +2,8 @@
  * device.h - generic, centralized driver model
  *
  * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
- * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (c) 2008-2009 Novell Inc.
  *
  * This file is released under the GPLv2
  *
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/semaphore.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/device.h>
 
-#define BUS_ID_SIZE            20
-
 struct device;
+struct device_private;
 struct device_driver;
 struct driver_private;
 struct class;
-struct class_private;
+struct subsys_private;
 struct bus_type;
-struct bus_type_private;
+struct device_node;
 
 struct bus_attribute {
        struct attribute        attr;
@@ -48,6 +47,38 @@ extern int __must_check bus_create_file(struct bus_type *,
                                        struct bus_attribute *);
 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
 
+/**
+ * struct bus_type - The bus type of the device
+ *
+ * @name:      The name of the bus.
+ * @bus_attrs: Default attributes of the bus.
+ * @dev_attrs: Default attributes of the devices on the bus.
+ * @drv_attrs: Default attributes of the device drivers on the bus.
+ * @match:     Called, perhaps multiple times, whenever a new device or driver
+ *             is added for this bus. It should return a nonzero value if the
+ *             given device can be handled by the given driver.
+ * @uevent:    Called when a device is added, removed, or a few other things
+ *             that generate uevents to add the environment variables.
+ * @probe:     Called when a new device or driver add to this bus, and callback
+ *             the specific driver's probe to initial the matched device.
+ * @remove:    Called when a device removed from this bus.
+ * @shutdown:  Called at shut-down time to quiesce the device.
+ * @suspend:   Called when a device on this bus wants to go to sleep mode.
+ * @resume:    Called to bring a device on this bus out of sleep mode.
+ * @pm:                Power management operations of this bus, callback the specific
+ *             device driver's pm-ops.
+ * @p:         The private data of the driver core, only the driver core can
+ *             touch this.
+ *
+ * A bus is a channel between the processor and one or more devices. For the
+ * purposes of the device model, all devices are connected via a bus, even if
+ * it is an internal, virtual, "platform" bus. Buses can plug into each other.
+ * A USB controller is usually a PCI device, for example. The device model
+ * represents the actual connections between buses and the devices they control.
+ * A bus is represented by the bus_type structure. It contains the name, the
+ * default attributes, the bus' methods, PM operations, and the driver core's
+ * private data.
+ */
 struct bus_type {
        const char              *name;
        struct bus_attribute    *bus_attrs;
@@ -61,13 +92,11 @@ struct bus_type {
        void (*shutdown)(struct device *dev);
 
        int (*suspend)(struct device *dev, pm_message_t state);
-       int (*suspend_late)(struct device *dev, pm_message_t state);
-       int (*resume_early)(struct device *dev);
        int (*resume)(struct device *dev);
 
-       struct pm_ext_ops *pm;
+       const struct dev_pm_ops *pm;
 
-       struct bus_type_private *p;
+       struct subsys_private *p;
 };
 
 extern int __must_check bus_register(struct bus_type *bus);
@@ -86,10 +115,12 @@ struct device *bus_find_device_by_name(struct bus_type *bus,
                                       struct device *start,
                                       const char *name);
 
-int __must_check bus_for_each_drv(struct bus_type *bus,
-                                 struct device_driver *start, void *data,
-                                 int (*fn)(struct device_driver *, void *));
+int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
+                    void *data, int (*fn)(struct device_driver *, void *));
 
+void bus_sort_breadthfirst(struct bus_type *bus,
+                          int (*compare)(const struct device *a,
+                                         const struct device *b));
 /*
  * Bus notifiers: Get notified of addition/removal of devices
  * and binding/unbinding of drivers to devices.
@@ -105,32 +136,71 @@ extern int bus_unregister_notifier(struct bus_type *bus,
 
 /* All 4 notifers below get called with the target struct device *
  * as an argument. Note that those functions are likely to be called
- * with the device semaphore held in the core, so be careful.
+ * with the device lock held in the core, so be careful.
  */
 #define BUS_NOTIFY_ADD_DEVICE          0x00000001 /* device added */
 #define BUS_NOTIFY_DEL_DEVICE          0x00000002 /* device removed */
-#define BUS_NOTIFY_BOUND_DRIVER                0x00000003 /* driver bound to device */
-#define BUS_NOTIFY_UNBIND_DRIVER       0x00000004 /* driver about to be
+#define BUS_NOTIFY_BIND_DRIVER         0x00000003 /* driver about to be
+                                                     bound */
+#define BUS_NOTIFY_BOUND_DRIVER                0x00000004 /* driver bound to device */
+#define BUS_NOTIFY_UNBIND_DRIVER       0x00000005 /* driver about to be
                                                      unbound */
+#define BUS_NOTIFY_UNBOUND_DRIVER      0x00000006 /* driver is unbound
+                                                     from the device */
 
 extern struct kset *bus_get_kset(struct bus_type *bus);
 extern struct klist *bus_get_device_klist(struct bus_type *bus);
 
+/**
+ * struct device_driver - The basic device driver structure
+ * @name:      Name of the device driver.
+ * @bus:       The bus which the device of this driver belongs to.
+ * @owner:     The module owner.
+ * @mod_name:  Used for built-in modules.
+ * @suppress_bind_attrs: Disables bind/unbind via sysfs.
+ * @of_match_table: The open firmware table.
+ * @probe:     Called to query the existence of a specific device,
+ *             whether this driver can work with it, and bind the driver
+ *             to a specific device.
+ * @remove:    Called when the device is removed from the system to
+ *             unbind a device from this driver.
+ * @shutdown:  Called at shut-down time to quiesce the device.
+ * @suspend:   Called to put the device to sleep mode. Usually to a
+ *             low power state.
+ * @resume:    Called to bring a device from sleep mode.
+ * @groups:    Default attributes that get created by the driver core
+ *             automatically.
+ * @pm:                Power management operations of the device which matched
+ *             this driver.
+ * @p:         Driver core's private data, no one other than the driver
+ *             core can touch this.
+ *
+ * The device driver-model tracks all of the drivers known to the system.
+ * The main reason for this tracking is to enable the driver core to match
+ * up drivers with new devices. Once drivers are known objects within the
+ * system, however, a number of other things become possible. Device drivers
+ * can export information and configuration variables that are independent
+ * of any specific device.
+ */
 struct device_driver {
        const char              *name;
        struct bus_type         *bus;
 
        struct module           *owner;
-       const char              *mod_name;      /* used for built-in modules */
+       const char              *mod_name;      /* used for built-in modules */
+
+       bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */
+
+       const struct of_device_id       *of_match_table;
 
        int (*probe) (struct device *dev);
        int (*remove) (struct device *dev);
        void (*shutdown) (struct device *dev);
        int (*suspend) (struct device *dev, pm_message_t state);
        int (*resume) (struct device *dev);
-       struct attribute_group **groups;
+       const struct attribute_group **groups;
 
-       struct pm_ops *pm;
+       const struct dev_pm_ops *pm;
 
        struct driver_private *p;
 };
@@ -144,6 +214,8 @@ extern void put_driver(struct device_driver *drv);
 extern struct device_driver *driver_find(const char *name,
                                         struct bus_type *bus);
 extern int driver_probe_done(void);
+extern void wait_for_device_probe(void);
+
 
 /* sysfs interface for exporting driver attributes */
 
@@ -159,9 +231,9 @@ struct driver_attribute driver_attr_##_name =               \
        __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check driver_create_file(struct device_driver *driver,
-                                          struct driver_attribute *attr);
+                                       const struct driver_attribute *attr);
 extern void driver_remove_file(struct device_driver *driver,
-                              struct driver_attribute *attr);
+                              const struct driver_attribute *attr);
 
 extern int __must_check driver_add_kobj(struct device_driver *drv,
                                        struct kobject *kobj,
@@ -176,8 +248,34 @@ struct device *driver_find_device(struct device_driver *drv,
                                  struct device *start, void *data,
                                  int (*match)(struct device *dev, void *data));
 
-/*
- * device classes
+/**
+ * struct class - device classes
+ * @name:      Name of the class.
+ * @owner:     The module owner.
+ * @class_attrs: Default attributes of this class.
+ * @dev_attrs: Default attributes of the devices belong to the class.
+ * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
+ * @dev_kobj:  The kobject that represents this class and links it into the hierarchy.
+ * @dev_uevent:        Called when a device is added, removed from this class, or a
+ *             few other things that generate uevents to add the environment
+ *             variables.
+ * @devnode:   Callback to provide the devtmpfs.
+ * @class_release: Called to release this class.
+ * @dev_release: Called to release the device.
+ * @suspend:   Used to put the device to sleep mode, usually to a low power
+ *             state.
+ * @resume:    Used to bring the device from the sleep mode.
+ * @ns_type:   Callbacks so sysfs can detemine namespaces.
+ * @namespace: Namespace of the device belongs to this class.
+ * @pm:                The default device power management operations of this class.
+ * @p:         The private data of the driver core, no one other than the
+ *             driver core can touch this.
+ *
+ * A class is a higher-level view of a device that abstracts out low-level
+ * implementation details. Drivers may see a SCSI disk or an ATA disk, but,
+ * at the class level, they are all simply disks. Classes allow user space
+ * to work with devices based on what they do, rather than how they are
+ * connected or how they work.
  */
 struct class {
        const char              *name;
@@ -185,9 +283,11 @@ struct class {
 
        struct class_attribute          *class_attrs;
        struct device_attribute         *dev_attrs;
+       struct bin_attribute            *dev_bin_attrs;
        struct kobject                  *dev_kobj;
 
        int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
+       char *(*devnode)(struct device *dev, mode_t *mode);
 
        void (*class_release)(struct class *class);
        void (*dev_release)(struct device *dev);
@@ -195,8 +295,17 @@ struct class {
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
 
-       struct pm_ops *pm;
-       struct class_private *p;
+       const struct kobj_ns_type_operations *ns_type;
+       const void *(*namespace)(struct device *dev);
+
+       const struct dev_pm_ops *pm;
+
+       struct subsys_private *p;
+};
+
+struct class_dev_iter {
+       struct klist_iter               ki;
+       const struct device_type        *type;
 };
 
 extern struct kobject *sysfs_dev_block_kobj;
@@ -213,6 +322,21 @@ extern void class_unregister(struct class *class);
        __class_register(class, &__key);        \
 })
 
+struct class_compat;
+struct class_compat *class_compat_register(const char *name);
+void class_compat_unregister(struct class_compat *cls);
+int class_compat_create_link(struct class_compat *cls, struct device *dev,
+                            struct device *device_link);
+void class_compat_remove_link(struct class_compat *cls, struct device *dev,
+                             struct device *device_link);
+
+extern void class_dev_iter_init(struct class_dev_iter *iter,
+                               struct class *class,
+                               struct device *start,
+                               const struct device_type *type);
+extern struct device *class_dev_iter_next(struct class_dev_iter *iter);
+extern void class_dev_iter_exit(struct class_dev_iter *iter);
+
 extern int class_for_each_device(struct class *class, struct device *start,
                                 void *data,
                                 int (*fn)(struct device *dev, void *data));
@@ -222,8 +346,10 @@ extern struct device *class_find_device(struct class *class,
 
 struct class_attribute {
        struct attribute attr;
-       ssize_t (*show)(struct class *class, char *buf);
-       ssize_t (*store)(struct class *class, const char *buf, size_t count);
+       ssize_t (*show)(struct class *class, struct class_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct class *class, struct class_attribute *attr,
+                       const char *buf, size_t count);
 };
 
 #define CLASS_ATTR(_name, _mode, _show, _store)                        \
@@ -234,6 +360,23 @@ extern int __must_check class_create_file(struct class *class,
 extern void class_remove_file(struct class *class,
                              const struct class_attribute *attr);
 
+/* Simple class attribute that is just a static string */
+
+struct class_attribute_string {
+       struct class_attribute attr;
+       char *str;
+};
+
+/* Currently read-only only */
+#define _CLASS_ATTR_STRING(_name, _mode, _str) \
+       { __ATTR(_name, _mode, show_class_attr_string, NULL), _str }
+#define CLASS_ATTR_STRING(_name, _mode, _str) \
+       struct class_attribute_string class_attr_##_name = \
+               _CLASS_ATTR_STRING(_name, _mode, _str)
+
+extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
+                        char *buf);
+
 struct class_interface {
        struct list_head        node;
        struct class            *class;
@@ -269,14 +412,12 @@ extern void class_destroy(struct class *cls);
  */
 struct device_type {
        const char *name;
-       struct attribute_group **groups;
+       const struct attribute_group **groups;
        int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
+       char *(*devnode)(struct device *dev, mode_t *mode);
        void (*release)(struct device *dev);
 
-       int (*suspend)(struct device *dev, pm_message_t state);
-       int (*resume)(struct device *dev);
-
-       struct pm_ops *pm;
+       const struct dev_pm_ops *pm;
 };
 
 /* interface for exporting device attributes */
@@ -292,13 +433,13 @@ struct device_attribute {
 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check device_create_file(struct device *device,
-                                          struct device_attribute *entry);
+                                       const struct device_attribute *entry);
 extern void device_remove_file(struct device *dev,
-                              struct device_attribute *attr);
+                              const struct device_attribute *attr);
 extern int __must_check device_create_bin_file(struct device *dev,
-                                              struct bin_attribute *attr);
+                                       const struct bin_attribute *attr);
 extern void device_remove_bin_file(struct device *dev,
-                                  struct bin_attribute *attr);
+                                  const struct bin_attribute *attr);
 extern int device_schedule_callback_owner(struct device *dev,
                void (*func)(struct device *dev), struct module *owner);
 
@@ -349,29 +490,84 @@ struct device_dma_parameters {
        unsigned long segment_boundary_mask;
 };
 
+/**
+ * struct device - The basic device structure
+ * @parent:    The device's "parent" device, the device to which it is attached.
+ *             In most cases, a parent device is some sort of bus or host
+ *             controller. If parent is NULL, the device, is a top-level device,
+ *             which is not usually what you want.
+ * @p:         Holds the private data of the driver core portions of the device.
+ *             See the comment of the struct device_private for detail.
+ * @kobj:      A top-level, abstract class from which other classes are derived.
+ * @init_name: Initial name of the device.
+ * @type:      The type of device.
+ *             This identifies the device type and carries type-specific
+ *             information.
+ * @mutex:     Mutex to synchronize calls to its driver.
+ * @bus:       Type of bus device is on.
+ * @driver:    Which driver has allocated this
+ * @platform_data: Platform data specific to the device.
+ *             Example: For devices on custom boards, as typical of embedded
+ *             and SOC based hardware, Linux often uses platform_data to point
+ *             to board-specific structures describing devices and how they
+ *             are wired.  That can include what ports are available, chip
+ *             variants, which GPIO pins act in what additional roles, and so
+ *             on.  This shrinks the "Board Support Packages" (BSPs) and
+ *             minimizes board-specific #ifdefs in drivers.
+ * @power:     For device power management.
+ *             See Documentation/power/devices.txt for details.
+ * @pm_domain: Provide callbacks that are executed during system suspend,
+ *             hibernation, system resume and during runtime PM transitions
+ *             along with subsystem-level and driver-level callbacks.
+ * @numa_node: NUMA node this device is close to.
+ * @dma_mask:  Dma mask (if dma'ble device).
+ * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
+ *             hardware supports 64-bit addresses for consistent allocations
+ *             such descriptors.
+ * @dma_parms: A low level driver may set these to teach IOMMU code about
+ *             segment limitations.
+ * @dma_pools: Dma pools (if dma'ble device).
+ * @dma_mem:   Internal for coherent mem override.
+ * @archdata:  For arch-specific additions.
+ * @of_node:   Associated device tree node.
+ * @devt:      For creating the sysfs "dev".
+ * @devres_lock: Spinlock to protect the resource of the device.
+ * @devres_head: The resources list of the device.
+ * @knode_class: The node used to add the device to the class list.
+ * @class:     The class of the device.
+ * @groups:    Optional attribute groups.
+ * @release:   Callback to free the device after all references have
+ *             gone away. This should be set by the allocator of the
+ *             device (i.e. the bus driver that discovered the device).
+ *
+ * At the lowest level, every device in a Linux system is represented by an
+ * instance of struct device. The device structure contains the information
+ * that the device model core needs to model the system. Most subsystems,
+ * however, track additional information about the devices they host. As a
+ * result, it is rare for devices to be represented by bare device structures;
+ * instead, that structure, like kobject structures, is usually embedded within
+ * a higher-level representation of the device.
+ */
 struct device {
-       struct klist            klist_children;
-       struct klist_node       knode_parent;   /* node in sibling list */
-       struct klist_node       knode_driver;
-       struct klist_node       knode_bus;
        struct device           *parent;
 
+       struct device_private   *p;
+
        struct kobject kobj;
-       char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
-       struct device_type      *type;
-       unsigned                uevent_suppress:1;
+       const char              *init_name; /* initial name of the device */
+       const struct device_type *type;
 
-       struct semaphore        sem;    /* semaphore to synchronize calls to
+       struct mutex            mutex;  /* mutex to synchronize calls to
                                         * its driver.
                                         */
 
        struct bus_type *bus;           /* type of bus device is on */
        struct device_driver *driver;   /* which driver has allocated this
                                           device */
-       void            *driver_data;   /* data private to the driver */
        void            *platform_data; /* Platform specific data, device
                                           core doesn't touch it */
        struct dev_pm_info      power;
+       struct dev_pm_domain    *pm_domain;
 
 #ifdef CONFIG_NUMA
        int             numa_node;      /* NUMA node this device is close to */
@@ -392,13 +588,16 @@ struct device {
        /* arch specific additions */
        struct dev_archdata     archdata;
 
+       struct device_node      *of_node; /* associated device tree node */
+
+       dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
+
        spinlock_t              devres_lock;
        struct list_head        devres_head;
 
-       struct list_head        node;
+       struct klist_node       knode_class;
        struct class            *class;
-       dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
-       struct attribute_group  **groups;       /* optional groups */
+       const struct attribute_group **groups;  /* optional groups */
 
        void    (*release)(struct device *dev);
 };
@@ -408,8 +607,11 @@ struct device {
 
 static inline const char *dev_name(const struct device *dev)
 {
-       /* will be changed into kobject_name(&dev->kobj) in the near future */
-       return dev->bus_id;
+       /* Use the init name until the kobject becomes available */
+       if (dev->init_name)
+               return dev->init_name;
+
+       return kobject_name(&dev->kobj);
 }
 
 extern int dev_set_name(struct device *dev, const char *name, ...)
@@ -434,14 +636,14 @@ static inline void set_dev_node(struct device *dev, int node)
 }
 #endif
 
-static inline void *dev_get_drvdata(struct device *dev)
+static inline unsigned int dev_get_uevent_suppress(const struct device *dev)
 {
-       return dev->driver_data;
+       return dev->kobj.uevent_suppress;
 }
 
-static inline void dev_set_drvdata(struct device *dev, void *data)
+static inline void dev_set_uevent_suppress(struct device *dev, int val)
 {
-       dev->driver_data = data;
+       dev->kobj.uevent_suppress = val;
 }
 
 static inline int device_is_registered(struct device *dev)
@@ -449,6 +651,38 @@ static inline int device_is_registered(struct device *dev)
        return dev->kobj.state_in_sysfs;
 }
 
+static inline void device_enable_async_suspend(struct device *dev)
+{
+       if (!dev->power.is_prepared)
+               dev->power.async_suspend = true;
+}
+
+static inline void device_disable_async_suspend(struct device *dev)
+{
+       if (!dev->power.is_prepared)
+               dev->power.async_suspend = false;
+}
+
+static inline bool device_async_suspend_enabled(struct device *dev)
+{
+       return !!dev->power.async_suspend;
+}
+
+static inline void device_lock(struct device *dev)
+{
+       mutex_lock(&dev->mutex);
+}
+
+static inline int device_trylock(struct device *dev)
+{
+       return mutex_trylock(&dev->mutex);
+}
+
+static inline void device_unlock(struct device *dev)
+{
+       mutex_unlock(&dev->mutex);
+}
+
 void driver_init(void);
 
 /*
@@ -463,8 +697,29 @@ extern int device_for_each_child(struct device *dev, void *data,
                     int (*fn)(struct device *dev, void *data));
 extern struct device *device_find_child(struct device *dev, void *data,
                                int (*match)(struct device *dev, void *data));
-extern int device_rename(struct device *dev, char *new_name);
-extern int device_move(struct device *dev, struct device *new_parent);
+extern int device_rename(struct device *dev, const char *new_name);
+extern int device_move(struct device *dev, struct device *new_parent,
+                      enum dpm_order dpm_order);
+extern const char *device_get_devnode(struct device *dev,
+                                     mode_t *mode, const char **tmp);
+extern void *dev_get_drvdata(const struct device *dev);
+extern int dev_set_drvdata(struct device *dev, void *data);
+
+/*
+ * Root device objects for grouping under /sys/devices
+ */
+extern struct device *__root_device_register(const char *name,
+                                            struct module *owner);
+static inline struct device *root_device_register(const char *name)
+{
+       return __root_device_register(name, THIS_MODULE);
+}
+extern void root_device_unregister(struct device *root);
+
+static inline void *dev_get_platdata(const struct device *dev)
+{
+       return dev->platform_data;
+}
 
 /*
  * Manual binding of a device to driver. See drivers/base/bus.c
@@ -489,7 +744,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
                                    dev_t devt, void *drvdata,
                                    const char *fmt, ...)
                                    __attribute__((format(printf, 5, 6)));
-#define device_create_drvdata  device_create
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
@@ -503,60 +757,151 @@ extern int (*platform_notify)(struct device *dev);
 extern int (*platform_notify_remove)(struct device *dev);
 
 
-/**
+/*
  * get_device - atomically increment the reference count for the device.
  *
  */
 extern struct device *get_device(struct device *dev);
 extern void put_device(struct device *dev);
 
+extern void wait_for_device_probe(void);
+
+#ifdef CONFIG_DEVTMPFS
+extern int devtmpfs_create_node(struct device *dev);
+extern int devtmpfs_delete_node(struct device *dev);
+extern int devtmpfs_mount(const char *mntdir);
+#else
+static inline int devtmpfs_create_node(struct device *dev) { return 0; }
+static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
+static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
+#endif
 
 /* drivers/base/power/shutdown.c */
 extern void device_shutdown(void);
 
-/* drivers/base/sys.c */
-extern void sysdev_shutdown(void);
-
 /* debugging and troubleshooting/diagnostic helpers. */
 extern const char *dev_driver_string(const struct device *dev);
-#define dev_printk(level, dev, format, arg...) \
-       printk(level "%s %s: " format , dev_driver_string(dev) , \
-              dev_name(dev) , ## arg)
-
-#define dev_emerg(dev, format, arg...)         \
-       dev_printk(KERN_EMERG , dev , format , ## arg)
-#define dev_alert(dev, format, arg...)         \
-       dev_printk(KERN_ALERT , dev , format , ## arg)
-#define dev_crit(dev, format, arg...)          \
-       dev_printk(KERN_CRIT , dev , format , ## arg)
-#define dev_err(dev, format, arg...)           \
-       dev_printk(KERN_ERR , dev , format , ## arg)
-#define dev_warn(dev, format, arg...)          \
-       dev_printk(KERN_WARNING , dev , format , ## arg)
-#define dev_notice(dev, format, arg...)                \
-       dev_printk(KERN_NOTICE , dev , format , ## arg)
-#define dev_info(dev, format, arg...)          \
-       dev_printk(KERN_INFO , dev , format , ## arg)
-
-#ifdef DEBUG
-#define dev_dbg(dev, format, arg...)           \
-       dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+
+#ifdef CONFIG_PRINTK
+
+extern int dev_printk(const char *level, const struct device *dev,
+                     const char *fmt, ...)
+       __attribute__ ((format (printf, 3, 4)));
+extern int dev_emerg(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int dev_alert(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int dev_crit(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int dev_err(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int dev_warn(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int dev_notice(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+extern int _dev_info(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+
 #else
+
+static inline int dev_printk(const char *level, const struct device *dev,
+                     const char *fmt, ...)
+       __attribute__ ((format (printf, 3, 4)));
+static inline int dev_printk(const char *level, const struct device *dev,
+                     const char *fmt, ...)
+        { return 0; }
+
+static inline int dev_emerg(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_emerg(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int dev_crit(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_crit(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int dev_alert(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_alert(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int dev_err(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_err(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int dev_warn(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_warn(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int dev_notice(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int dev_notice(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+static inline int _dev_info(const struct device *dev, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+static inline int _dev_info(const struct device *dev, const char *fmt, ...)
+       { return 0; }
+
+#endif
+
+/*
+ * Stupid hackaround for existing uses of non-printk uses dev_info
+ *
+ * Note that the definition of dev_info below is actually _dev_info
+ * and a macro is used to avoid redefining dev_info
+ */
+
+#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
+
+#if defined(DEBUG)
 #define dev_dbg(dev, format, arg...)           \
-       ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+       dev_printk(KERN_DEBUG, dev, format, ##arg)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+#define dev_dbg(dev, format, ...)                   \
+do {                                                \
+       dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
+} while (0)
+#else
+#define dev_dbg(dev, format, arg...)                           \
+({                                                             \
+       if (0)                                                  \
+               dev_printk(KERN_DEBUG, dev, format, ##arg);     \
+       0;                                                      \
+})
 #endif
 
 #ifdef VERBOSE_DEBUG
 #define dev_vdbg       dev_dbg
 #else
-
-#define dev_vdbg(dev, format, arg...)          \
-       ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+#define dev_vdbg(dev, format, arg...)                          \
+({                                                             \
+       if (0)                                                  \
+               dev_printk(KERN_DEBUG, dev, format, ##arg);     \
+       0;                                                      \
+})
 #endif
 
+/*
+ * dev_WARN*() acts like dev_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define dev_WARN(dev, format, arg...) \
+       WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg);
+
+#define dev_WARN_ONCE(dev, condition, format, arg...) \
+       WARN_ONCE(condition, "Device %s\n" format, \
+                       dev_driver_string(dev), ## arg)
+
 /* Create alias, so I can be autoloaded. */
 #define MODULE_ALIAS_CHARDEV(major,minor) \
        MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_CHARDEV_MAJOR(major) \
        MODULE_ALIAS("char-major-" __stringify(major) "-*")
+
+#ifdef CONFIG_SYSFS_DEPRECATED
+extern long sysfs_deprecated;
+#else
+#define sysfs_deprecated 0
+#endif
+
 #endif /* _DEVICE_H_ */