1. Introduction
In the 2.4 and earlier Linux kernels, there was no unified database of
what devices were present in the system, and how they were connected
with each other. The implications of this are:
The five software components that play a major role in building and maintaining the device model are:
-
The user had to grep through log messages to find out if a
particular device has been detected by the kernel or not. There was
no straight forward method for an application to list out what
devices have been detected by the kernel, and whether a driver has
been associated with the device.
-
It was not possible to do proper power management, because this
requires information on how the devices are connected in a
system. As an example, before a USB controller is powered down, all
the USB peripherals connected to that controller had to be powered
down.
The five software components that play a major role in building and maintaining the device model are:
-
the device model core
-
the generic bus drivers
-
the bus controller drivers
-
the device drivers
-
the class drivers
2. Device Model Core
The device model core defines a set of structures and functions. The
structures form the building blocks of the device model and the
functions update and maintain the device model.
Some of the important structures defined by the device model core are given below.
The device model core, among other things, defines functions to register and unregister instances of the above structures. These functions are listed below.
Some of the important structures defined by the device model core are given below.
-
struct bus_type
-
struct device
-
struct device_driver
-
struct class
The device model core, among other things, defines functions to register and unregister instances of the above structures. These functions are listed below.
-
bus_register()
-
bus_unregister()
-
device_register()
-
device_unregister()
-
driver_register()
-
driver_unregister()
-
class_register()
-
class_unregister()
3. Generic Bus Drivers
For each bus supported by the kernel there is a generic bus
driver. The generic bus driver allocates a struct bus_type and
registers it with the kernel's list of bus types. The registration is
done using bus_register(). (bus_type_register() would have been a
more appropriate name!).
The important fields of the bus_type structure are shown below.
The fields marked with a ! are internal to the device model core and
should not be touched by the generic bus driver directly.
Given below is a sample of bus_type instantiation for the PHY management bus, taken from drivers/net/phy/mdio_bus.c.
Apart from defining a bus_type, the generic bus driver defines a bus
specific driver structure and a bus specific device structure. These
structures extend the generic struct device_driver and struct
device provided by the device model core, by adding bus specific
members.
The generic bus driver provides helper functions to register and unregister device drivers that can handle devices on that bus. These helper functions wrap the generic functions provided by the device model core.
The important fields of the bus_type structure are shown below.
bus_type |-- name (string) |-- !klist_devices (klist) |-- !klist_drivers (klist) |-- match (fp) |-- suspend (fp) `-- resume (fp)
-
The name member provides a human readable representation of the bus
type, example: pci, usb, mdio.
-
The klist_drivers member is a list of drivers that can handle
devices on that bus. This list is updated by the driver_register()
which is called when a driver initializes itself.
-
The klist_devices member is a list of devices in the system that
reside on this particular type of bus. This list is updated by
device_register() which is called when the bus is scanned for
devices by the bus controller driver (during initialization or when
a gadget is hot plugged.)
-
When a new gadget is plugged into the system, the bus controller
driver detects the device and calls device_register() the list of
drivers associated with the bus is iterated over to find out if
there are any drivers that can handle the device. The match
function provided in the bus_type structure is used to check if a
given driver can handle a given device.
-
When a driver module is inserted into the kernel and the driver
calls driver_register(), the list of devices associated with the
bus is iterated over to find out if there are any devices that the
driver can handle. The match function is used for this purpose.
Given below is a sample of bus_type instantiation for the PHY management bus, taken from drivers/net/phy/mdio_bus.c.
struct bus_type mdio_bus_type = { .name = "mdio_bus", .match = mdio_bus_match, .suspend = mdio_bus_suspend, .resume = mdio_bus_resume, };
The generic bus driver provides helper functions to register and unregister device drivers that can handle devices on that bus. These helper functions wrap the generic functions provided by the device model core.
4. Bus Controller Drivers
For a specific bus type there could be many different controllers
provided by different vendors. Each of these controllers needs a
corresponding bus controller driver. The role of a bus controller
driver in maintenance of the device model, is similar to that of any
other device driver in that, it registers itself with
driver_register(). But apart from registering itself, it also
detects devices on the bus it is controlling and registers the devices
on the bus using device_register().
The bus controller driver is responsible for instantiating and registering instances of struct device with the device model core. Some of the important members of struct device are given below.
The fields marked with a ! are internal to the device model core and
should not be touched by the bus controller driver directly.
The bus controller driver is responsible for instantiating and registering instances of struct device with the device model core. Some of the important members of struct device are given below.
device |-- bus_id (string) |-- bus (bus_type) |-- parent (device) `-- !driver (device_driver)
-
The bus_id member is a unique name for the device within a bus type.
-
The bus member is a pointer to the bus_type to which this device
belongs to.
-
When a device is registered by the bus controller driver, the
parent member is pointed to the bus controller device so as to
build the physical device tree.
-
When a binding occurs and a driver is found that can handle the
device, the driver member is pointed to the corresponding device
driver.
5. Device Drivers
Every device driver registers itself with the bus_type using
driver_register(). After which the device model core tries to bind
it with a device. When a device is detected (registered) that can be
handled by a particular driver, the probe member of the driver is
called to instantiate the driver for that particular device.
Each device driver is responsible for instantiating and registering an instance of struct device_driver with the device model core. The important members of struct device_driver is given below.
Each device driver is responsible for instantiating and registering an instance of struct device_driver with the device model core. The important members of struct device_driver is given below.
device_driver |-- bus (bus_type) |-- probe (fp) |-- remove (fp) |-- suspend (fp) `-- resume (fp)
-
The bus member is a pointer to the bus_type to which the device
driver is registered.
-
The probe member is a callback function which is called for each
device detected that is supported by the driver. The driver should
instantiate itself for each device and initialize the device as
well.
-
The remove member is a callback function is called to unbind the
driver from the device. This happens when the device is physically
removed, when the driver is unloaded, or when the system is
shutdown.
6. Class Drivers
Most users of a system are not bothered about how devices are
connected in a system, but what type of devices are connected in the
system. A class driver instantiates a struct class for the class of
devices it represents and registers it with the device model core
using class_register(). Each device driver is responsible for adding
its device to the appropriate class.
The important members of struct class is given below.
The fields marked with a ! mark are internal to the device model
core and should not be touched by the class driver directly.
The important members of struct class is given below.
class |-- name (string) `-- !devices (list)
-
name is the human readable name given to the instance of struct
class like graphics, sound, etc.
-
devices is a list of devices that belong to a particular instance
of the class. The devices list is updated by the device drivers
when the instantiate themselves for a device.
7. Conclusion
With these data structures in place, a device tree of how the devices
are connected in the system are available, and what types of devices
are present in the system is also available. This overcomes the
limitations of the 2.4 kernel, and paves way for
|-- name (string)
|-- parent (kobject’s parent)
|-- ktype ( type associated with a kobject)
|-- kset (group of kobjects all of which are embedded in structures of the same type)
|-- sd (points to a sysfs_dirent structure that represents this kobject in sysfs.)
|-- kref (provides reference counting)
-
better power management implementations
- better instrospection of devices connected to the system
Linux Device Model Detailed
Device
model is one of most integral and least looked part of kernel. Since
during normal kernel development, most aspects of device model are
either left untouched or are taken for granted.
With this article, I have made an honest attempt to decode everything that lies beneath.
The motive is to help reader understand the philosophy and working of LDM (Linux Device Model)
The
initial motivation for the device model was this final point: providing an accurate device tree to facilitate power management.
To
implement device-level power management in the kernel, you need to build a tree
representing the device topology in the system: for example, what drive
connects to what controller, and what device connects to what bus. When
powering down, the kernel must power down the lower (leaf) nodes of the tree
before the higher nodes. For example, before a USB controller is powered down,
all the USB peripherals connected to that controller had to be powered down.
A unified
device model was added in Linux kernel to provide a single mechanism for representing
devices and describing their topology in the system. Such a system provides
several benefits:
- Minimization of code duplication
- A mechanism for providing common facilities, such as reference counting
- Capability to determine all the devices in the system, view their status and power state, see to what bus they are attached, and which driver is responsible for them
- The capability to generate a complete and valid tree of the entire device structure of the system, including all buses and interconnections
- The capability to link devices to their drivers and vice versa
- Categorize devices by their kind (“classes”), such as input device, without the need to understand the physical device topology
- Power Management - The capability to walk the tree of devices from the leaves up to the root, powering down devices in the correct order
The device model brings with it a whole new
vocabulary to describe its data structures. A quick overview of some device model
terms appears below; much of this stuff will be looked at in detail later on.
device
A physical or virtual object which attaches to a (possibly virtual) bus.
driver
A software entity which may probe for and be bound to devices, and which
can perform certain management functions.
bus
A device which serves as an attachment point for other devices.
class
A particular type of device which can be expected to perform in certain
ways. Classes might include disks, partitions, serial ports, etc.
subsystem
A top-level
view of the system's structure. Subsystems used in the kernel
include devices (a hierarchical view of all devices on the
system), bus (a bus-oriented view), class(devices by
class), net (the networking subsystem), and others. The best way to
think of a subsystem, perhaps, is as a particular view into the device model
data structure rather than a physical component of the system. The same objects
(devices, usually) show up in most subsystems, but they are organized
differently.
The
fundamental task of the device model is to maintain a set of internal data
structures which reflect the architecture and state of the underlying system. The
device model works by tracking system configuration changes (hardware and
software) and maintaining a complex "web woven by a spider on drugs"
data structure to represent it all.
In order
to understand device model, it is of utmost importance to first understand the
low lying structures and their relationship with each other. Interface to the
sysfs virtual file system is out of scope of this article. Without going deep in
the details, here is what you should know about them.
Kobjects
At the
heart of the device model is the kobject, short for kernel object, which is
represented
by struct kobject and defined in
<linux/kobject.h>. It provides basic facilities, such as reference
counting, a name, and a parent pointer, enabling the creation of a hierarchy of
objects.
Even though, in most of
cases, you will never have to manipulate a kobject directly, it is hard to dig
very deeply into the driver model without encountering them. Kobjects are
usually embedded in other structures. Some of the important fields are:
struct kobject|-- name (string)
|-- parent (kobject’s parent)
|-- ktype ( type associated with a kobject)
|-- kset (group of kobjects all of which are embedded in structures of the same type)
|-- sd (points to a sysfs_dirent structure that represents this kobject in sysfs.)
|-- kref (provides reference counting)
It is the glue that holds much of the device model
and its sysfs interface together.
For initialization and setup
of kobjects, following functions exist:
void kobject_put(struct kobject *kobj);
|-- sysfs_ops (describes the behavior of sysfs files on read and write)
|-- default_attrs (default attributes associated with this kobject)
behavior.
|-- kobj (kobject representing the base class for this set)
|-- uevent_ops (describes the hotplug behavior of kobjects in this kset)
int kset_register(struct kset *kset);
Following functions manage the reference counts of ksets :
A kset, too, has a name, which is stored in the embedded kobject whose name is set by:
Device
Model Core
|-- p (subsys_private)
|-- klist_devices (klist)
|-- klist_drivers (klist)
|-- drivers_kset
|-- devices_kset
|-- match (fp)
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
For a specific bus type there could be many different controllers provided by different vendors. Each of these controllers needs a corresponding bus controller driver. The role of a bus controller driver in maintenance of the device model, is similar to that of any other device driver in that, it registers itself with driver_register(). But apart from registering itself, it also detects devices on the bus it is controlling and registers the devices on the bus usingdevice_register().
|-- bus (bus_type)
|-- parent (device)
|-- driver (device_driver)
|-- probe (fp)
|-- remove (fp)
|-- p (driver_private)
|-- p (subsys_private)
name is the human readable name given to the instance of struct class like graphics, sound, etc.
Defined in driver/base/core.c, this function does following initialization:
Defined in driver/base/bus.c, this function does following initialization:
static struct platform_device uart8250_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = uart8250_data,
},
};
return platform_device_register(&uart8250_device);
}
.remove = __devexit_p(serial8250_remove),
.suspend = serial8250_suspend,
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
.owner = THIS_MODULE,
},
};
int ret;
…
ret = platform_driver_register(&serial8250_isa_driver);
…
platform_driver_register():
driver_find():
void kobject_init(struct
kobject *kobj);
Kobject users must, at a
minimum, set the name of the kobject; this is the name that will be used in
sysfs entries
kobject_set_name(struct kobject *kobj,
"The name");
Following functions manage
the reference counts of kobjects :
struct kobject
*kobject_get(struct kobject *kobj);void kobject_put(struct kobject *kobj);
To create sysfs entries
int kobject_add(struct kobject *kobj);
void
kobject_del(struct kobject *kobj);
There is
a kobject_register() function, which is really just the combination
of the calls to kobject_init() and kobject_add().
Similarly, kobject_unregister() will call kobject_del(), then
call kobject_put() to release the initial reference created
with kobject_register() (or really kobject_init()).
Ktypes
Kobjects
are associated with a specific type, called a ktype, short for kernel object
type.
Ktypes
are represented by struct kobj_type and defined in <linux/kobject.h>
struct kobj_type
|--
release (pointer points to the deconstructor)|-- sysfs_ops (describes the behavior of sysfs files on read and write)
|-- default_attrs (default attributes associated with this kobject)
Ktypes
have the simple job of describing default behavior for a family of kobjects.
Instead
of each kobject defining its own behavior, the behavior is stored in a ktype,
and
kobjects
of the same “type” point at the same ktype structure, thus sharing the samebehavior.
Every kobject needs to have an associated kobj_type structure
and every kobject must have a release() method, and the kobject must
persist (in a consistent state) until that method is called. If these
constraints are not met, the code is flawed.
Ksets
Ksets,
short for kernel object sets, are aggregate collections of kobjects. Ksets work
as the
base
container class for a set of kernel objects, collecting related kobjects, such
as “all block devices,” together in a single place.
The kset
pointer points at a kobject’s associated kset. ksets are represented by the
kset
structure,
which is declared in <linux/kobject.h>
struct kset
|-- list
(linked list of all kobjects in this kset)|-- kobj (kobject representing the base class for this set)
|-- uevent_ops (describes the hotplug behavior of kobjects in this kset)
Ksets
group related kernel objects together, whereas ktypes enable kernel objects (functionally
related or not) to share common operations.
The
distinction is kept to allow kobjects of identical ktypes to be grouped into
different ksets.
A kset serves these
functions:
- It serves as a bag containing a group of identical objects. A kset can be used by the kernel to track "all block devices" or "all PCI device drivers."
- A kset is the directory-level glue that holds the device model (and sysfs) together. Every kset contains a kobject which can be set up to be the parent of other kobjects; in this way the device model hierarchy is constructed.
- Ksets can support the "hotplugging" of kobjects and influence how hotplug events are reported to user space.
void kset_init(struct
kset *kset);
int
kset_add(struct kset *kset);int kset_register(struct kset *kset);
void
kset_unregister(struct kset *kset);
Following functions manage the reference counts of ksets :
struct
kset *kset_get(struct kset *kset);
void
kset_put(struct kset *kset);A kset, too, has a name, which is stored in the embedded kobject whose name is set by:
kobject_set_name(my_set->kobj, "The name");
Having understood low lying structures and before
we start digging inside the kernel code, let’s look at some of other important
structures and functions which are building blocks of device model.
Some of the important structures defined by the device model core are
given below.
- struct bus_type
- struct device
- struct device_driver
- struct class
The struct bus_type is used to represent buses like PCI, USB,
I2C, etc. The struct device is used to represent devices like an
Intel AC97 audio controller, an Intel PRO/100 ethernet controller, a PS/2 mouse
etc. The struct device_driver is used to represent kernel drivers
that can handle specific devices. The struct class is used to
represent a class of devices like sound, input, graphics, etc. no matter how
they are connected to the system.
The device model core, among other things, defines functions to register and unregister instances
of the above structures. These functions are listed below.
- bus_register()
- bus_unregister()
- device_register()
- device_unregister()
- driver_register()
- driver_unregister()
- class_register()
- class_unregister()
Generic Bus
Drivers
For each bus supported by the kernel there is a generic bus driver. The
generic bus driver allocates a struct bus_type and registers it with
the kernel's list of bus types. The registration is done
using bus_register().
The important fields of the struct bus_type structure are shown below.
struct bus_type
|-- name (string)|-- p (subsys_private)
|-- klist_devices (klist)
|-- klist_drivers (klist)
|-- drivers_kset
|-- devices_kset
|-- match (fp)
- The name member provides a human readable representation of the bus type, example: platform, pci, usb etc.
- The klist_drivers member is a list of drivers that can handle devices on that bus. This list is updated by the driver_register() which is called when a driver initializes itself.
- The klist_devices member is a list of devices in the system that reside on this particular type of bus. This list is updated by device_register() which is called when the bus is scanned for devices by the bus controller driver (during initialization or when a gadget is hot plugged.)
- When a new gadget is plugged into the system, the bus controller driver detects the device and calls device_register() the list of drivers associated with the bus is iterated over to find out if there are any drivers that can handle the device. The match function provided in the bus_type structure is used to check if a given driver can handle a given device.
- When a driver module is inserted into the kernel and the driver calls driver_register(), the list of devices associated with the bus is iterated over to find out if there are any devices that the driver can handle. The match function is used for this purpose.
When a match is found, the device is
associated with the device driver. The process of associating a device with a
device driver is called binding.
Given below is a sample of bus_type instantiation for the platform bus,
taken from drivers/base/platform.c.
struct bus_type platform_bus_type = {
.name = "platform",.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
Apart from defining a bus_type, the generic
bus driver defines a bus specific driver structure and a bus specific device
structure. These structures extend the generic struct
device_driver and struct device provided by the device model
core, by adding bus specific members.
The generic bus driver provides helper functions to register and
unregister device drivers that can handle devices on that bus. These helper
functions wrap the generic functions provided by the device model core.
Bus
Controller Drivers
For a specific bus type there could be many different controllers provided by different vendors. Each of these controllers needs a corresponding bus controller driver. The role of a bus controller driver in maintenance of the device model, is similar to that of any other device driver in that, it registers itself with driver_register(). But apart from registering itself, it also detects devices on the bus it is controlling and registers the devices on the bus usingdevice_register().
The bus controller driver is responsible for instantiating and
registering instances of struct device with the device model core.
Some of the important members of struct device are given below.
struct device
|-- init_name (string)|-- bus (bus_type)
|-- parent (device)
|-- driver (device_driver)
- The init_name member is a unique name for the device within a bus type.
- The bus member is a pointer to the bus_type to which this device belongs to.
- When a device is registered by the bus controller driver, the parent member is pointed to the bus controller device so as to build the physical device tree.
- When a binding occurs and a driver is found that can handle the device, the driver member is pointed to the corresponding device driver.
Device
Drivers
Every device driver registers itself with the bus_type
using driver_register(). After which the device model core tries to bind
it with a device. When a device is detected (registered) that can be handled by
a particular driver, theprobe member of the driver is called to
instantiate the driver for that particular device.
Each device driver is responsible for instantiating and registering an
instance of struct device_driver with the device model core. The
important members of struct device_driver is given below.
struct device_driver
|-- bus (bus_type)|-- probe (fp)
|-- remove (fp)
|-- p (driver_private)
- The bus member is a pointer to the bus_type to which the device driver is registered.
- The probe member is a callback function which is called for each device detected that is supported by the driver. The driver should instantiate itself for each device and initialize the device as well.
- The remove member is a callback function is called to unbind the driver from the device. This happens when the device is physically removed, when the driver is unloaded, or when the system is shutdown.
Class
Drivers
Most users of a system are not bothered about how devices are connected
in a system, but what type of devices are connected in the system. A class
driver instantiates a struct class for the class of devices it
represents and registers it with the device model core
using class_register(). Each device driver is responsible for adding its
device to the appropriate class.
The important members of struct class is given below.
struct class
|-- name (string)|-- p (subsys_private)
name is the human readable name given to the instance of struct class like graphics, sound, etc.
Now it is time to see how things are being done
inside kernel.
During kernel startup, driver_init() is the function call which initializes driver model.
It is defined in drivers/base/init.c
This in-turn calls the driver model init functions
to initialize their subsystems:
devices_init():
Defined in driver/base/core.c, this function does
following initializations:
- create a struct kset “devices_kset “ dynamically and add it to sysfs (/sys/devices) using function kset_create_and_add().
- create a struct kobject “dev_kobj“ dynamically and register it with sysfs (/sys/dev) using function kobject_create_and_add()
- creates struct kobject “sysfs_dev_block_kobj and sysfs_dev_char_kobj “ dynamically with parent as “dev_kobj” and register it with sysfs (/sys/dev/block, /sys/dev/char respectively) using function kobject_create_and_add()
Important point to note here is while creating
sysfs_dev_block_kobj and
sysfs_dev_char_kobj kobjects, parent kobject used is
“dev_kobj” and thus, sysfs entries are created within “/sys/dev”.
buses_init():
Defined in driver/base/bus.c, this function does
following initializations:
- create a struct kset “bus_kset “ dynamically and register it with sysfs (/sys/bus) using function kset_create_and_add()
- create a struct kset “system_kset “ dynamically with parent as “devices_kset->kobj” and register it with sysfs (/sys/devices/system) using function kset_create_and_add()
Defined in driver/base/class.c, this function does
following initialization:
- create a struct kset “class_kset “ dynamically and register it with sysfs (/sys/class) using function kset_create_and_add()
platform_bus_init():
Defined in driver/base/platform.c, this function
does following initialization:
device_register():
Defined in driver/base/core.c, this function does following initialization:
- register “platform” bus device with system using function device_register().
device_initialize():
- initialize “device” structure
- set dev->kobj.kset = devices_kset
- initialize dev->kobj with ktype = devices_ktype
device_add():
- add “platform” device to device hierarchy (/sys/device/platform)
bus_add_device()
- add device to bus’s list of devices
bus_probe_device()
- probe for a driver for new device if bus allows it
device_attach()
- try to attach device to a driver by walking the list of drivers that the bus has and call driver_probe_device() for each pair.
Defined in driver/base/bus.c, this function does following initialization:
- register a driver-core subsystem and then register the children subsystems it has
- allocate memory to struct subsys_private *priv
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
priv->devices_kset =
kset_create_and_add("devices", NULL,
&priv->subsys.kobj);
priv->drivers_kset =
kset_create_and_add("drivers", NULL,
&priv->subsys.kobj);
- Thus we have following directories:
/sys/bus/platform/devices
/sys/bus/platform/drivers
Now you understand why it is referred to as complex "web woven by a spider on
drugs" data structure to represent it all.
After driver_init(), kernel is ready with solid base of device
model. From now onwards, all you have to do is simply call device and driver
register functions and everything will be hooked to the right place right where
it belongs. Since we took platform bus as an example, we will quickly look what
happens when a platform device and a (corresponding) platform driver are
registered.
Let’s take example of simple uart8250 device as
reference
static struct platform_device uart8250_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = uart8250_data,
},
};
The important members of struct platform_device are given
below.
struct platform_device
|-- name (string)
|-- id (device instance number, or else "-1" to indicate there's only one)
|-- dev (struct device)
|-- platform_data
static int __init uart8250_init(void)
{return platform_device_register(&uart8250_device);
}
platform_device_register():
Defined in driver/base/platform.c, this function
does following initialization:
platform_device_add():
- add a platform device to device hierarchy
- struct platform_device *pdev
pdev->dev.bus = &platform_bus_type;
- add platform device “pdev->name” to device hierarchy (/sys/device/platform/ serial8250) by calling function device_add().
Once we have serial8250 platform device added,
corresponding platform driver will be registered.
static struct platform_driver serial8250_isa_driver
= {
.probe = serial8250_probe,.remove = __devexit_p(serial8250_remove),
.suspend = serial8250_suspend,
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
.owner = THIS_MODULE,
},
};
The important members of struct platform_driver are given
below.
struct platform_driver
|-- probe (function pointer)
|-- remove (function pointer)
|-- driver (struct device driver)
static int __init serial8250_init(void)
{int ret;
…
ret = platform_driver_register(&serial8250_isa_driver);
…
}
Defined in driver/base/platform.c, this function
does following initialization:
- set bus type of driver pointed by struct platform_driver *drv
drv->driver.bus
= &platform_bus_type;
- register driver with bus by calling driver_register().
driver_find():
- locate driver on a bus by its name
- Call kset_find_obj() to iterate over list of drivers on a bus to find driver by name
bus_add_drivers():
- Add a driver to the bus
- allocate memory to struct driver_private *priv
struct bus_type *bus;
bus = bus_get(drv->bus);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
kobject_init_and_add(&priv->kobj,
&driver_ktype, NULL, "%s", drv->name);
(/sys/devices/platform/serial8250/driver/serial8250)
- try to bind driver to devices by calling driver_attach()
- this in turn calls driver_probe_device() which calls really_probe() function which is defined in drivers/base/dd.c
- really_probe() adds driver in sysfs and calls probe() function of your platform device driver (serial8250_probe):
ret = drv->probe(dev);
With all this information at your dispense, I leave
you to explore the world of device model.
No comments:
Post a Comment