文章的分析基于linux-2.6.22
今天记录下 platform_bus_init过程中,platform_bus_type总线和platform_bus设备的注册,以及构建的目录结构。
1.
/**
* driver_init - initialize driver model.
*
* Call the driver model init functions to initialize their
* subsystems. Called early from init/main.c.
*/
void __init driver_init(void)
{
......
platform_bus_init();
......
}
2.
int __init platform_bus_init(void)
{
int error;
error = device_register(&platform_bus); //2.1分析
if (error)
return error;
error = bus_register(&platform_bus_type); //2.2分析
if (error)
device_unregister(&platform_bus);
return error;
}
struct device platform_bus = {
.bus_id = "platform",
};
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.suspend = platform_suspend,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
};
2.1
/**
* device_register - register a device with the system.
* @dev: pointer to the device structure
*
* This happens in two clean steps - initialize the device
* and add it to the system. The two steps can be called
* separately, but this is the easiest and most common.
* I.e. you should only call the two helpers separately if
* have a clearly defined need to use and refcount the device
* before it is added to the hierarchy.
*/
int device_register(struct device *dev)
{
device_initialize(dev); //2.1.1分析
return device_add(dev); //2.1.2分析
}
2.1.1
/**
* device_initialize - init device structure.
* @dev: device.
*
* This prepares the device for use by other layers,
* including adding it to the device hierarchy.
* It is the first half of device_register(), if called by
* that, though it can also be called separately, so one
* may use @dev's fields (e.g. the refcount).
*/
//devices_subsys的目录名为devices
void device_initialize(struct device *dev)
{
......
kobj_set_kset_s(dev, devices_subsys); //设置dev的kset指向devices_subsys
.......
INIT_LIST_HEAD(&dev->node);
.......
}
2.1.2
/**
* device_add - add device to device hierarchy.
* @dev: device.
*
* This is part 2 of device_register(), though may be called
* separately _iff_ device_initialize() has been called separately.
*
* This adds it to the kobject hierarchy via kobject_add(), adds it
* to the global and sibling lists for the device, then
* adds it to the other relevant subsystems of the driver model.
*/
int device_add(struct device *dev)
{
......
kobject_set_name(&dev->kobj, "%s", dev->bus_id);
error = kobject_add(&dev->kobj); //设置dev的parent,将其加人devices_subsys的链表
......
}
2.2
/**
* bus_register - register a bus with the system.
* @bus: bus.
*
* Once we have that, we registered the bus with the kobject
* infrastructure, then register the children subsystems it has:
* the devices and drivers that belong to the bus.
*/
//bus_subsys的目录名为bus
int bus_register(struct bus_type * bus)
{
......
retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
......
subsys_set_kset(bus, bus_subsys); //设置bus的kset的指向bus_subsys
retval = subsystem_register(&bus->subsys); //设置bus->subsys的parent,将其加入
//bus_subsys的链表
......
kobject_set_name(&bus->devices.kobj, "devices");
bus->devices.kobj.parent = &bus->subsys.kobj;
retval = kset_register(&bus->devices);
......
kobject_set_name(&bus->drivers.kobj, "drivers");
bus->drivers.kobj.parent = &bus->subsys.kobj;
bus->drivers.ktype = &ktype_driver;
retval = kset_register(&bus->drivers);
......
klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&bus->klist_drivers, NULL, NULL);
bus->drivers_autoprobe = 1;
}
图1:platform_bus和devices_subsys数据结构连接的简单示意,程序的2.1部分建立的devices/platform文件夹
图2:platform_bus_type和bus_subsys数据结构连接的简单示意,程序的2.2部分建立的bus/platform文件夹,然后创建了platform/devices和platform/drives