2005-04-17 02:20:36 +04:00
|
|
|
/*
|
|
|
|
* device.h - generic, centralized driver model
|
|
|
|
*
|
|
|
|
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
|
2007-02-13 09:33:06 +03:00
|
|
|
* Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
|
2005-04-17 02:20:36 +04:00
|
|
|
*
|
|
|
|
* This file is released under the GPLv2
|
|
|
|
*
|
|
|
|
* See Documentation/driver-model/ for more information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _DEVICE_H_
|
|
|
|
#define _DEVICE_H_
|
|
|
|
|
|
|
|
#include <linux/ioport.h>
|
|
|
|
#include <linux/kobject.h>
|
2005-03-21 22:49:14 +03:00
|
|
|
#include <linux/klist.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/list.h>
|
2006-08-15 09:43:17 +04:00
|
|
|
#include <linux/compiler.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/pm.h>
|
2008-04-19 06:21:05 +04:00
|
|
|
#include <linux/semaphore.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <asm/atomic.h>
|
2006-11-11 09:18:39 +03:00
|
|
|
#include <asm/device.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
#define DEVICE_NAME_SIZE 50
|
2008-01-25 08:04:46 +03:00
|
|
|
/* DEVICE_NAME_HALF is really less than half to accommodate slop */
|
|
|
|
#define DEVICE_NAME_HALF __stringify(20)
|
2005-04-17 02:20:36 +04:00
|
|
|
#define DEVICE_ID_SIZE 32
|
|
|
|
#define BUS_ID_SIZE KOBJ_NAME_LEN
|
|
|
|
|
|
|
|
|
|
|
|
struct device;
|
|
|
|
struct device_driver;
|
2007-11-29 02:59:15 +03:00
|
|
|
struct driver_private;
|
2005-04-17 02:20:36 +04:00
|
|
|
struct class;
|
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe
--w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind
devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.
Systems who want to control the driver binding with udev, switch off the
bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel"
ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom
bind/unbind-scripts and all the weird things people invented over the years.
It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the
third port of USB-hub by the "ub" driver, and everything else by
usb-storage. One can also instruct udev to bind different wireless
drivers to identical cards - just selected by the pcmcia slot-number, and
whatever ...
To use the mentioned rules, it needs udev version 106, to be able to
write ATTR{}="$kernel" to sysfs files.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-02-16 19:33:36 +03:00
|
|
|
struct bus_type;
|
2007-11-02 05:41:16 +03:00
|
|
|
struct bus_type_private;
|
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe
--w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind
devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.
Systems who want to control the driver binding with udev, switch off the
bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel"
ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom
bind/unbind-scripts and all the weird things people invented over the years.
It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the
third port of USB-hub by the "ub" driver, and everything else by
usb-storage. One can also instruct udev to bind different wireless
drivers to identical cards - just selected by the pcmcia slot-number, and
whatever ...
To use the mentioned rules, it needs udev version 106, to be able to
write ATTR{}="$kernel" to sysfs files.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-02-16 19:33:36 +03:00
|
|
|
|
|
|
|
struct bus_attribute {
|
|
|
|
struct attribute attr;
|
2008-01-25 08:04:46 +03:00
|
|
|
ssize_t (*show)(struct bus_type *bus, char *buf);
|
|
|
|
ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
|
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe
--w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind
devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.
Systems who want to control the driver binding with udev, switch off the
bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel"
ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom
bind/unbind-scripts and all the weird things people invented over the years.
It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the
third port of USB-hub by the "ub" driver, and everything else by
usb-storage. One can also instruct udev to bind different wireless
drivers to identical cards - just selected by the pcmcia slot-number, and
whatever ...
To use the mentioned rules, it needs udev version 106, to be able to
write ATTR{}="$kernel" to sysfs files.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-02-16 19:33:36 +03:00
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
#define BUS_ATTR(_name, _mode, _show, _store) \
|
|
|
|
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
|
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe
--w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind
devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.
Systems who want to control the driver binding with udev, switch off the
bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel"
ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom
bind/unbind-scripts and all the weird things people invented over the years.
It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the
third port of USB-hub by the "ub" driver, and everything else by
usb-storage. One can also instruct udev to bind different wireless
drivers to identical cards - just selected by the pcmcia slot-number, and
whatever ...
To use the mentioned rules, it needs udev version 106, to be able to
write ATTR{}="$kernel" to sysfs files.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-02-16 19:33:36 +03:00
|
|
|
|
|
|
|
extern int __must_check bus_create_file(struct bus_type *,
|
|
|
|
struct bus_attribute *);
|
|
|
|
extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
struct bus_type {
|
2008-01-25 08:04:46 +03:00
|
|
|
const char *name;
|
|
|
|
struct bus_attribute *bus_attrs;
|
|
|
|
struct device_attribute *dev_attrs;
|
|
|
|
struct driver_attribute *drv_attrs;
|
|
|
|
|
|
|
|
int (*match)(struct device *dev, struct device_driver *drv);
|
|
|
|
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
|
|
|
|
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 (*suspend_late)(struct device *dev, pm_message_t state);
|
|
|
|
int (*resume_early)(struct device *dev);
|
|
|
|
int (*resume)(struct device *dev);
|
Driver core: udev triggered device-<>driver binding
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe
--w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind
devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a
driver to this device.
Systems who want to control the driver binding with udev, switch off the
bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel"
ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom
bind/unbind-scripts and all the weird things people invented over the years.
It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the
third port of USB-hub by the "ub" driver, and everything else by
usb-storage. One can also instruct udev to bind different wireless
drivers to identical cards - just selected by the pcmcia slot-number, and
whatever ...
To use the mentioned rules, it needs udev version 106, to be able to
write ATTR{}="$kernel" to sysfs files.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-02-16 19:33:36 +03:00
|
|
|
|
2007-11-02 05:41:16 +03:00
|
|
|
struct bus_type_private *p;
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check bus_register(struct bus_type *bus);
|
|
|
|
extern void bus_unregister(struct bus_type *bus);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check bus_rescan_devices(struct bus_type *bus);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
/* iterator helpers for buses */
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
|
|
|
|
int (*fn)(struct device *dev, void *data));
|
|
|
|
struct device *bus_find_device(struct bus_type *bus, struct device *start,
|
|
|
|
void *data,
|
|
|
|
int (*match)(struct device *dev, void *data));
|
2008-01-27 21:29:20 +03:00
|
|
|
struct device *bus_find_device_by_name(struct bus_type *bus,
|
|
|
|
struct device *start,
|
|
|
|
const char *name);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2006-08-15 09:43:17 +04:00
|
|
|
int __must_check bus_for_each_drv(struct bus_type *bus,
|
2008-01-25 08:04:46 +03:00
|
|
|
struct device_driver *start, void *data,
|
|
|
|
int (*fn)(struct device_driver *, void *));
|
2005-04-17 02:20:36 +04:00
|
|
|
|
Driver core: add notification of bus events
I finally did as you suggested and added the notifier to the struct
bus_type itself. There are still problems to be expected is something
attaches to a bus type where the code can hook in different struct
device sub-classes (which is imho a big bogosity but I won't even try to
argue that case now) but it will solve nicely a number of issues I've
had so far.
That also means that clients interested in registering for such
notifications have to do it before devices are added and after bus types
are registered. Fortunately, most bus types that matter for the various
usage scenarios I have in mind are registerd at postcore_initcall time,
which means I have a really nice spot at arch_initcall time to add my
notifiers.
There are 4 notifications provided. Device being added (before hooked to
the bus) and removed (failure of previous case or after being unhooked
from the bus), along with driver being bound to a device and about to be
unbound.
The usage I have for these are:
- The 2 first ones are used to maintain a struct device_ext that is
hooked to struct device.firmware_data. This structure contains for now a
pointer to the Open Firmware node related to the device (if any), the
NUMA node ID (for quick access to it) and the DMA operations pointers &
iommu table instance for DMA to/from this device. For bus types I own
(like IBM VIO or EBUS), I just maintain that structure directly from the
bus code when creating the devices. But for bus types managed by generic
code like PCI or platform (actually, of_platform which is a variation of
platform linked to Open Firmware device-tree), I need this notifier.
- The other two ones have a completely different usage scenario. I have
cases where multiple devices and their drivers depend on each other. For
example, the IBM EMAC network driver needs to attach to a MAL DMA engine
which is a separate device, and a PHY interface which is also a separate
device. They are all of_platform_device's (well, about to be with my
upcoming patches) but there is no say in what precise order the core
will "probe" them and instanciate the various modules. The solution I
found for that is to have the drivers for emac to use multithread_probe,
and wait for a driver to be bound to the target MAL and PHY control
devices (the device-tree contains reference to the MAL and PHY interface
nodes, which I can then match to of_platform_devices). Right now, I've
been polling, but with that notifier, I can more cleanly wait (with a
timeout of course).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-10-25 07:44:59 +04:00
|
|
|
/*
|
|
|
|
* Bus notifiers: Get notified of addition/removal of devices
|
|
|
|
* and binding/unbinding of drivers to devices.
|
|
|
|
* In the long run, it should be a replacement for the platform
|
|
|
|
* notify hooks.
|
|
|
|
*/
|
|
|
|
struct notifier_block;
|
|
|
|
|
|
|
|
extern int bus_register_notifier(struct bus_type *bus,
|
|
|
|
struct notifier_block *nb);
|
|
|
|
extern int bus_unregister_notifier(struct bus_type *bus,
|
|
|
|
struct notifier_block *nb);
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
#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
|
|
|
|
unbound */
|
|
|
|
|
2007-11-02 05:41:16 +03:00
|
|
|
extern struct kset *bus_get_kset(struct bus_type *bus);
|
2007-11-02 05:41:16 +03:00
|
|
|
extern struct klist *bus_get_device_klist(struct bus_type *bus);
|
2007-11-02 05:41:16 +03:00
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
struct device_driver {
|
2007-11-29 02:59:15 +03:00
|
|
|
const char *name;
|
|
|
|
struct bus_type *bus;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2007-11-29 02:59:15 +03:00
|
|
|
struct module *owner;
|
|
|
|
const char *mod_name; /* used for built-in modules */
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
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);
|
2007-12-05 14:50:23 +03:00
|
|
|
struct attribute_group **groups;
|
2007-11-29 02:59:15 +03:00
|
|
|
|
|
|
|
struct driver_private *p;
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check driver_register(struct device_driver *drv);
|
|
|
|
extern void driver_unregister(struct device_driver *drv);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern struct device_driver *get_driver(struct device_driver *drv);
|
|
|
|
extern void put_driver(struct device_driver *drv);
|
|
|
|
extern struct device_driver *driver_find(const char *name,
|
|
|
|
struct bus_type *bus);
|
2006-07-18 21:59:59 +04:00
|
|
|
extern int driver_probe_done(void);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2007-02-17 21:13:42 +03:00
|
|
|
/* sysfs interface for exporting driver attributes */
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
struct driver_attribute {
|
2008-01-25 08:04:46 +03:00
|
|
|
struct attribute attr;
|
|
|
|
ssize_t (*show)(struct device_driver *driver, char *buf);
|
|
|
|
ssize_t (*store)(struct device_driver *driver, const char *buf,
|
|
|
|
size_t count);
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
#define DRIVER_ATTR(_name, _mode, _show, _store) \
|
|
|
|
struct driver_attribute driver_attr_##_name = \
|
|
|
|
__ATTR(_name, _mode, _show, _store)
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check driver_create_file(struct device_driver *driver,
|
|
|
|
struct driver_attribute *attr);
|
|
|
|
extern void driver_remove_file(struct device_driver *driver,
|
|
|
|
struct driver_attribute *attr);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2007-12-19 22:54:39 +03:00
|
|
|
extern int __must_check driver_add_kobj(struct device_driver *drv,
|
|
|
|
struct kobject *kobj,
|
|
|
|
const char *fmt, ...);
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check driver_for_each_device(struct device_driver *drv,
|
|
|
|
struct device *start,
|
|
|
|
void *data,
|
|
|
|
int (*fn)(struct device *dev,
|
|
|
|
void *));
|
|
|
|
struct device *driver_find_device(struct device_driver *drv,
|
|
|
|
struct device *start, void *data,
|
|
|
|
int (*match)(struct device *dev, void *data));
|
2005-03-21 21:59:56 +03:00
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
/*
|
|
|
|
* device classes
|
|
|
|
*/
|
|
|
|
struct class {
|
2008-01-25 08:04:46 +03:00
|
|
|
const char *name;
|
|
|
|
struct module *owner;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2007-04-14 00:15:19 +04:00
|
|
|
struct kset subsys;
|
2006-06-14 23:14:34 +04:00
|
|
|
struct list_head devices;
|
2005-04-17 02:20:36 +04:00
|
|
|
struct list_head interfaces;
|
2007-03-14 05:25:56 +03:00
|
|
|
struct kset class_dirs;
|
2008-01-22 10:27:08 +03:00
|
|
|
struct semaphore sem; /* locks children, devices, interfaces */
|
2008-01-25 08:04:46 +03:00
|
|
|
struct class_attribute *class_attrs;
|
|
|
|
struct device_attribute *dev_attrs;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
void (*class_release)(struct class *class);
|
|
|
|
void (*dev_release)(struct device *dev);
|
2006-06-25 01:50:29 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
int (*suspend)(struct device *dev, pm_message_t state);
|
|
|
|
int (*resume)(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check class_register(struct class *class);
|
|
|
|
extern void class_unregister(struct class *class);
|
2008-01-22 10:27:08 +03:00
|
|
|
extern int class_for_each_device(struct class *class, void *data,
|
|
|
|
int (*fn)(struct device *dev, void *data));
|
|
|
|
extern struct device *class_find_device(struct class *class, void *data,
|
|
|
|
int (*match)(struct device *, void *));
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
struct class_attribute {
|
2008-01-25 08:04:46 +03:00
|
|
|
struct attribute attr;
|
|
|
|
ssize_t (*show)(struct class *class, char *buf);
|
|
|
|
ssize_t (*store)(struct class *class, const char *buf, size_t count);
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
#define CLASS_ATTR(_name, _mode, _show, _store) \
|
|
|
|
struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store)
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check class_create_file(struct class *class,
|
|
|
|
const struct class_attribute *attr);
|
|
|
|
extern void class_remove_file(struct class *class,
|
|
|
|
const struct class_attribute *attr);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
struct class_interface {
|
|
|
|
struct list_head node;
|
|
|
|
struct class *class;
|
|
|
|
|
2006-09-13 17:34:05 +04:00
|
|
|
int (*add_dev) (struct device *, struct class_interface *);
|
|
|
|
void (*remove_dev) (struct device *, struct class_interface *);
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2006-08-15 09:43:17 +04:00
|
|
|
extern int __must_check class_interface_register(struct class_interface *);
|
2005-04-17 02:20:36 +04:00
|
|
|
extern void class_interface_unregister(struct class_interface *);
|
|
|
|
|
2006-09-13 17:34:05 +04:00
|
|
|
extern struct class *class_create(struct module *owner, const char *name);
|
2005-03-15 22:54:21 +03:00
|
|
|
extern void class_destroy(struct class *cls);
|
|
|
|
|
2007-03-12 23:08:57 +03:00
|
|
|
/*
|
|
|
|
* The type of device, "struct device" is embedded in. A class
|
|
|
|
* or bus can contain devices of different types
|
|
|
|
* like "partitions" and "disks", "mouse" and "event".
|
|
|
|
* This identifies the device type and carries type-specific
|
|
|
|
* information, equivalent to the kobj_type of a kobject.
|
|
|
|
* If "name" is specified, the uevent will contain it in
|
|
|
|
* the DEVTYPE variable.
|
|
|
|
*/
|
2006-10-07 23:54:55 +04:00
|
|
|
struct device_type {
|
2007-03-12 23:08:57 +03:00
|
|
|
const char *name;
|
2007-03-10 09:37:34 +03:00
|
|
|
struct attribute_group **groups;
|
2007-08-14 17:15:12 +04:00
|
|
|
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
|
2006-10-07 23:54:55 +04:00
|
|
|
void (*release)(struct device *dev);
|
2008-01-25 08:04:46 +03:00
|
|
|
int (*suspend)(struct device *dev, pm_message_t state);
|
|
|
|
int (*resume)(struct device *dev);
|
2006-10-07 23:54:55 +04:00
|
|
|
};
|
|
|
|
|
2005-10-01 16:49:43 +04:00
|
|
|
/* interface for exporting device attributes */
|
|
|
|
struct device_attribute {
|
|
|
|
struct attribute attr;
|
|
|
|
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf);
|
|
|
|
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count);
|
|
|
|
};
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
#define DEVICE_ATTR(_name, _mode, _show, _store) \
|
|
|
|
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
|
2005-10-01 16:49:43 +04:00
|
|
|
|
2006-08-15 09:43:17 +04:00
|
|
|
extern int __must_check device_create_file(struct device *device,
|
2008-01-25 08:04:46 +03:00
|
|
|
struct device_attribute *entry);
|
|
|
|
extern void device_remove_file(struct device *dev,
|
|
|
|
struct device_attribute *attr);
|
2006-09-19 20:39:19 +04:00
|
|
|
extern int __must_check device_create_bin_file(struct device *dev,
|
|
|
|
struct bin_attribute *attr);
|
|
|
|
extern void device_remove_bin_file(struct device *dev,
|
|
|
|
struct bin_attribute *attr);
|
2007-04-26 11:12:04 +04:00
|
|
|
extern int device_schedule_callback_owner(struct device *dev,
|
2008-01-25 08:04:46 +03:00
|
|
|
void (*func)(struct device *dev), struct module *owner);
|
2007-04-26 11:12:04 +04:00
|
|
|
|
|
|
|
/* This is a macro to avoid include problems with THIS_MODULE */
|
|
|
|
#define device_schedule_callback(dev, func) \
|
|
|
|
device_schedule_callback_owner(dev, func, THIS_MODULE)
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
|
|
|
|
/* device resource management */
|
|
|
|
typedef void (*dr_release_t)(struct device *dev, void *res);
|
|
|
|
typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
|
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_DEVRES
|
2008-01-25 08:04:46 +03:00
|
|
|
extern void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
const char *name);
|
|
|
|
#define devres_alloc(release, size, gfp) \
|
|
|
|
__devres_alloc(release, size, gfp, #release)
|
|
|
|
#else
|
2008-01-25 08:04:46 +03:00
|
|
|
extern void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
#endif
|
|
|
|
extern void devres_free(void *res);
|
|
|
|
extern void devres_add(struct device *dev, void *res);
|
2008-01-25 08:04:46 +03:00
|
|
|
extern void *devres_find(struct device *dev, dr_release_t release,
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
dr_match_t match, void *match_data);
|
2008-01-25 08:04:46 +03:00
|
|
|
extern void *devres_get(struct device *dev, void *new_res,
|
|
|
|
dr_match_t match, void *match_data);
|
|
|
|
extern void *devres_remove(struct device *dev, dr_release_t release,
|
|
|
|
dr_match_t match, void *match_data);
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
extern int devres_destroy(struct device *dev, dr_release_t release,
|
|
|
|
dr_match_t match, void *match_data);
|
|
|
|
|
|
|
|
/* devres group */
|
|
|
|
extern void * __must_check devres_open_group(struct device *dev, void *id,
|
|
|
|
gfp_t gfp);
|
|
|
|
extern void devres_close_group(struct device *dev, void *id);
|
|
|
|
extern void devres_remove_group(struct device *dev, void *id);
|
|
|
|
extern int devres_release_group(struct device *dev, void *id);
|
|
|
|
|
|
|
|
/* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */
|
|
|
|
extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
|
|
|
|
extern void devm_kfree(struct device *dev, void *p);
|
|
|
|
|
2008-02-05 09:27:55 +03:00
|
|
|
struct device_dma_parameters {
|
|
|
|
/*
|
|
|
|
* a low level driver may set these to teach IOMMU code about
|
|
|
|
* sg limitations.
|
|
|
|
*/
|
|
|
|
unsigned int max_segment_size;
|
|
|
|
unsigned long segment_boundary_mask;
|
|
|
|
};
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
struct device {
|
2005-03-25 06:08:30 +03:00
|
|
|
struct klist klist_children;
|
2008-01-25 08:04:46 +03:00
|
|
|
struct klist_node knode_parent; /* node in sibling list */
|
2005-03-21 23:25:36 +03:00
|
|
|
struct klist_node knode_driver;
|
2005-03-21 22:49:14 +03:00
|
|
|
struct klist_node knode_bus;
|
2007-05-08 11:29:39 +04:00
|
|
|
struct device *parent;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
struct kobject kobj;
|
|
|
|
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
|
2006-10-07 23:54:55 +04:00
|
|
|
struct device_type *type;
|
2007-05-08 11:29:39 +04:00
|
|
|
unsigned uevent_suppress:1;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2005-03-21 21:41:04 +03:00
|
|
|
struct semaphore sem; /* semaphore to synchronize calls to
|
|
|
|
* its driver.
|
|
|
|
*/
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
struct bus_type *bus; /* type of bus device is on */
|
2005-04-17 02:20:36 +04:00
|
|
|
struct device_driver *driver; /* which driver has allocated this
|
|
|
|
device */
|
|
|
|
void *driver_data; /* data private to the driver */
|
2005-03-19 02:45:35 +03:00
|
|
|
void *platform_data; /* Platform specific data, device
|
|
|
|
core doesn't touch it */
|
2005-04-17 02:20:36 +04:00
|
|
|
struct dev_pm_info power;
|
|
|
|
|
2006-12-07 07:32:33 +03:00
|
|
|
#ifdef CONFIG_NUMA
|
|
|
|
int numa_node; /* NUMA node this device is close to */
|
|
|
|
#endif
|
2005-04-17 02:20:36 +04:00
|
|
|
u64 *dma_mask; /* dma mask (if dma'able device) */
|
|
|
|
u64 coherent_dma_mask;/* Like dma_mask, but for
|
|
|
|
alloc_coherent mappings as
|
|
|
|
not all hardware supports
|
|
|
|
64 bit addresses for consistent
|
|
|
|
allocations such descriptors. */
|
|
|
|
|
2008-02-05 09:27:55 +03:00
|
|
|
struct device_dma_parameters *dma_parms;
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
struct list_head dma_pools; /* dma pools (if dma'ble) */
|
|
|
|
|
|
|
|
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
|
|
|
|
override */
|
2006-11-11 09:18:39 +03:00
|
|
|
/* arch specific additions */
|
|
|
|
struct dev_archdata archdata;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
devres: device resource management
Implement device resource management, in short, devres. A device
driver can allocate arbirary size of devres data which is associated
with a release function. On driver detach, release function is
invoked on the devres data, then, devres data is freed.
devreses are typed by associated release functions. Some devreses are
better represented by single instance of the type while others need
multiple instances sharing the same release function. Both usages are
supported.
devreses can be grouped using devres group such that a device driver
can easily release acquired resources halfway through initialization
or selectively release resources (e.g. resources for port 1 out of 4
ports).
This patch adds devres core including documentation and the following
managed interfaces.
* alloc/free : devm_kzalloc(), devm_kzfree()
* IO region : devm_request_region(), devm_release_region()
* IRQ : devm_request_irq(), devm_free_irq()
* DMA : dmam_alloc_coherent(), dmam_free_coherent(),
dmam_declare_coherent_memory(), dmam_pool_create(),
dmam_pool_destroy()
* PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed()
* iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(),
devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(),
pcim_iomap(), pcim_iounmap()
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
2007-01-20 10:00:26 +03:00
|
|
|
spinlock_t devres_lock;
|
|
|
|
struct list_head devres_head;
|
|
|
|
|
2006-06-14 23:14:34 +04:00
|
|
|
struct list_head node;
|
2006-10-07 23:54:55 +04:00
|
|
|
struct class *class;
|
2008-01-25 08:04:46 +03:00
|
|
|
dev_t devt; /* dev_t, creates the sysfs "dev" */
|
2006-06-27 11:06:09 +04:00
|
|
|
struct attribute_group **groups; /* optional groups */
|
2006-06-14 23:14:34 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
void (*release)(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2008-03-20 00:39:13 +03:00
|
|
|
/* Get the wakeup routines, which depend on struct device */
|
|
|
|
#include <linux/pm_wakeup.h>
|
|
|
|
|
2008-05-02 08:02:41 +04:00
|
|
|
static inline const char *dev_name(struct device *dev)
|
|
|
|
{
|
|
|
|
/* will be changed into kobject_name(&dev->kobj) in the near future */
|
|
|
|
return dev->bus_id;
|
|
|
|
}
|
|
|
|
|
2006-12-07 07:32:33 +03:00
|
|
|
#ifdef CONFIG_NUMA
|
|
|
|
static inline int dev_to_node(struct device *dev)
|
|
|
|
{
|
|
|
|
return dev->numa_node;
|
|
|
|
}
|
|
|
|
static inline void set_dev_node(struct device *dev, int node)
|
|
|
|
{
|
|
|
|
dev->numa_node = node;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int dev_to_node(struct device *dev)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
static inline void set_dev_node(struct device *dev, int node)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
static inline void *dev_get_drvdata(struct device *dev)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
|
|
|
return dev->driver_data;
|
|
|
|
}
|
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
static inline void dev_set_drvdata(struct device *dev, void *data)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
|
|
|
dev->driver_data = data;
|
|
|
|
}
|
|
|
|
|
2005-09-22 11:47:24 +04:00
|
|
|
static inline int device_is_registered(struct device *dev)
|
|
|
|
{
|
2008-03-14 00:07:03 +03:00
|
|
|
return dev->kobj.state_in_sysfs;
|
2005-09-22 11:47:24 +04:00
|
|
|
}
|
|
|
|
|
2006-12-20 00:01:28 +03:00
|
|
|
void driver_init(void);
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
/*
|
|
|
|
* High level routines for use by the bus drivers
|
|
|
|
*/
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int __must_check device_register(struct device *dev);
|
|
|
|
extern void device_unregister(struct device *dev);
|
|
|
|
extern void device_initialize(struct device *dev);
|
|
|
|
extern int __must_check device_add(struct device *dev);
|
|
|
|
extern void device_del(struct device *dev);
|
|
|
|
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));
|
2006-07-04 01:31:12 +04:00
|
|
|
extern int device_rename(struct device *dev, char *new_name);
|
2006-11-20 19:07:51 +03:00
|
|
|
extern int device_move(struct device *dev, struct device *new_parent);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Manual binding of a device to driver. See drivers/base/bus.c
|
|
|
|
* for information on use.
|
|
|
|
*/
|
2006-08-15 09:43:20 +04:00
|
|
|
extern int __must_check device_bind_driver(struct device *dev);
|
2008-01-25 08:04:46 +03:00
|
|
|
extern void device_release_driver(struct device *dev);
|
|
|
|
extern int __must_check device_attach(struct device *dev);
|
2006-08-15 09:43:20 +04:00
|
|
|
extern int __must_check driver_attach(struct device_driver *drv);
|
|
|
|
extern int __must_check device_reprobe(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2006-06-14 23:14:34 +04:00
|
|
|
/*
|
|
|
|
* Easy functions for dynamically creating devices on the fly
|
|
|
|
*/
|
|
|
|
extern struct device *device_create(struct class *cls, struct device *parent,
|
2006-08-10 09:19:19 +04:00
|
|
|
dev_t devt, const char *fmt, ...)
|
2008-01-25 08:04:46 +03:00
|
|
|
__attribute__((format(printf, 4, 5)));
|
2006-06-14 23:14:34 +04:00
|
|
|
extern void device_destroy(struct class *cls, dev_t devt);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Platform "fixup" functions - allow the platform to have their say
|
|
|
|
* about devices and actions that the general device layer doesn't
|
|
|
|
* know about.
|
|
|
|
*/
|
|
|
|
/* Notify platform of device discovery */
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int (*platform_notify)(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-01-25 08:04:46 +03:00
|
|
|
extern int (*platform_notify_remove)(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get_device - atomically increment the reference count for the device.
|
|
|
|
*
|
|
|
|
*/
|
2008-01-25 08:04:46 +03:00
|
|
|
extern struct device *get_device(struct device *dev);
|
|
|
|
extern void put_device(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
|
2006-03-22 02:58:53 +03:00
|
|
|
/* drivers/base/power/shutdown.c */
|
2005-04-17 02:20:36 +04:00
|
|
|
extern void device_shutdown(void);
|
|
|
|
|
2007-07-26 18:29:55 +04:00
|
|
|
/* drivers/base/sys.c */
|
|
|
|
extern void sysdev_shutdown(void);
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
/* debugging and troubleshooting/diagnostic helpers. */
|
2006-06-17 01:10:48 +04:00
|
|
|
extern const char *dev_driver_string(struct device *dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
#define dev_printk(level, dev, format, arg...) \
|
2008-01-25 08:04:46 +03:00
|
|
|
printk(level "%s %s: " format , dev_driver_string(dev) , \
|
2008-05-02 08:02:41 +04:00
|
|
|
dev_name(dev) , ## arg)
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2007-10-30 22:37:14 +03:00
|
|
|
#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)
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
#define dev_dbg(dev, format, arg...) \
|
|
|
|
dev_printk(KERN_DEBUG , dev , format , ## arg)
|
|
|
|
#else
|
driver core: Convert debug functions declared inline __attribute__((format (printf,x,y) to statement expression macros
When DEBUG is not defined, pr_debug and dev_dbg and some
other local debugging functions are specified as:
"inline __attribute__((format (printf, x, y)))"
This is done to validate printk arguments when not debugging.
Converting these functions to macros or statement expressions
"do { if (0) printk(fmt, ##arg); } while (0)"
or
"({ if (0) printk(fmt, ##arg); 0; })
makes at least gcc 4.2.2 produce smaller objects.
This has the additional benefit of allowing the optimizer to
avoid calling functions like print_mac that might have been
arguments to the printk.
defconfig x86 current:
$ size vmlinux
text data bss dec hex filename
4716770 474560 618496 5809826 58a6a2 vmlinux
all converted: (More patches follow)
$ size vmlinux
text data bss dec hex filename
4716642 474560 618496 5809698 58a622 vmlinux
Even kernel/sched.o, which doesn't even use these
functions, becomes smaller.
It appears that merely having an indirect include
of <linux/device.h> can cause bigger objects.
$ size sched.inline.o sched.if0.o
text data bss dec hex filename
31385 2854 328 34567 8707 sched.inline.o
31366 2854 328 34548 86f4 sched.if0.o
The current preprocessed only kernel/sched.i file contains:
# 612 "include/linux/device.h"
static inline __attribute__((always_inline)) int __attribute__ ((format (printf, 2, 3)))
dev_dbg(struct device *dev, const char *fmt, ...)
{
return 0;
}
# 628 "include/linux/device.h"
static inline __attribute__((always_inline)) int __attribute__ ((format (printf, 2, 3)))
dev_vdbg(struct device *dev, const char *fmt, ...)
{
return 0;
}
Removing these unused inlines from sched.i shrinks sched.o
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-02-27 06:08:42 +03:00
|
|
|
#define dev_dbg(dev, format, arg...) \
|
|
|
|
({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
|
2005-04-17 02:20:36 +04:00
|
|
|
#endif
|
|
|
|
|
2007-07-13 09:08:22 +04:00
|
|
|
#ifdef VERBOSE_DEBUG
|
|
|
|
#define dev_vdbg dev_dbg
|
|
|
|
#else
|
driver core: Convert debug functions declared inline __attribute__((format (printf,x,y) to statement expression macros
When DEBUG is not defined, pr_debug and dev_dbg and some
other local debugging functions are specified as:
"inline __attribute__((format (printf, x, y)))"
This is done to validate printk arguments when not debugging.
Converting these functions to macros or statement expressions
"do { if (0) printk(fmt, ##arg); } while (0)"
or
"({ if (0) printk(fmt, ##arg); 0; })
makes at least gcc 4.2.2 produce smaller objects.
This has the additional benefit of allowing the optimizer to
avoid calling functions like print_mac that might have been
arguments to the printk.
defconfig x86 current:
$ size vmlinux
text data bss dec hex filename
4716770 474560 618496 5809826 58a6a2 vmlinux
all converted: (More patches follow)
$ size vmlinux
text data bss dec hex filename
4716642 474560 618496 5809698 58a622 vmlinux
Even kernel/sched.o, which doesn't even use these
functions, becomes smaller.
It appears that merely having an indirect include
of <linux/device.h> can cause bigger objects.
$ size sched.inline.o sched.if0.o
text data bss dec hex filename
31385 2854 328 34567 8707 sched.inline.o
31366 2854 328 34548 86f4 sched.if0.o
The current preprocessed only kernel/sched.i file contains:
# 612 "include/linux/device.h"
static inline __attribute__((always_inline)) int __attribute__ ((format (printf, 2, 3)))
dev_dbg(struct device *dev, const char *fmt, ...)
{
return 0;
}
# 628 "include/linux/device.h"
static inline __attribute__((always_inline)) int __attribute__ ((format (printf, 2, 3)))
dev_vdbg(struct device *dev, const char *fmt, ...)
{
return 0;
}
Removing these unused inlines from sched.i shrinks sched.o
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-02-27 06:08:42 +03:00
|
|
|
|
|
|
|
#define dev_vdbg(dev, format, arg...) \
|
|
|
|
({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
|
2007-07-13 09:08:22 +04:00
|
|
|
#endif
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
/* 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) "-*")
|
|
|
|
#endif /* _DEVICE_H_ */
|