一、平台设备platform_device的添加过程
1. 定义dm9000的platform_device结构体,并初始化
在arch/arm/mach-s3c64xx/mach-smdk6410.c中定义了dm9000的platform_device
-
static struct platform_device smdk6410_device_eth = {
-
.name = "dm9000",
-
.id = -1,
-
.num_resources = ARRAY_SIZE(smdk6410_dm9000_resource),
-
.resource = smdk6410_dm9000_resource,
-
.dev = {
-
.platform_data = &smdk6410_dm9000_pdata,
-
},
-
};
2. 设备的注册过程
将dm9000的platform_device结构体添加到数组中
在arch/arm/mach-s3c64xx/mach-smdk6410.c中
-
static struct platform_device *smdk6410_devices[] __initdata = {
-
&smdk6410_device_eth, //把dm9000添加到device数组中
-
};
-
-
static void __init smdk6410_machine_init(void)
-
{
-
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
-
}
在driver/bash/platform.c中
-
int platform_add_devices(struct platform_device **devs, int num)
-
{
-
for (i = 0; i < num; i++)
-
ret = platform_device_register(devs[i]);
-
}
platform_add_devices ;add多个devices
--> platform_device_add ;add单个devices
-
int platform_device_add(struct platform_device *pdev)
-
{
-
//如果platform_device没有parent的话,默认把parent设为platform_bus
-
if (!pdev->dev.parent)
-
pdev->dev.parent = &platform_bus;
-
//设定总线的match uevent函数指针
-
pdev->dev.bus = &platform_bus_type;
-
-
if (pdev->id != -1)
-
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
-
else
-
dev_set_name(&pdev->dev, "%s", pdev->name);
-
//下面这部分是配置resource
-
for (i = 0; i < pdev->num_resources; i++) {
-
struct resource *p, *r = &pdev->resource[i];
-
if (r->name == NULL)
-
r->name = dev_name(&pdev->dev);
-
p = r->parent;
-
if (!p) {
-
if (resource_type(r) == IORESOURCE_MEM)
-
p = &iomem_resource;
-
else if (resource_type(r) == IORESOURCE_IO)
-
p = &ioport_resource;
-
}
-
if (p && insert_resource(p, r)) {
-
ret = -EBUSY;
-
goto failed;
-
}
-
}
-
ret = device_add(&pdev->dev); //2.1
-
}
2.1 device_add
platform_add_devices ;add多个devices
--> platform_device_add ;add单个devices
--> device_add
-
int device_add(struct device *dev)
-
{
-
struct class_interface *class_intf;
-
if (!dev->p) {
-
error = device_private_init(dev);
-
}
-
if (dev->init_name) {
-
dev_set_name(dev, "%s", dev->init_name);
-
dev->init_name = NULL;
-
}
-
parent = get_device(dev->parent);
-
setup_parent(dev, parent);
-
if (parent)
-
set_dev_node(dev, dev_to_node(parent));
-
-
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
-
if (platform_notify)
-
platform_notify(dev);
-
//在sysfs目录下为device创建文件
-
error = device_create_file(dev, &uevent_attr);
-
-
if (MAJOR(dev->devt)) {
-
device_create_file(dev, &devt_attr);
-
device_create_sys_dev_entry(dev);
-
devtmpfs_create_node(dev);
-
}
-
device_add_class_symlinks(dev);
-
device_add_attrs(dev);
-
bus_add_device(dev); //将设备添加到总线下,说白了就是在链表里面加个值klist_add_tail
-
dpm_sysfs_add(dev);
-
device_pm_add(dev);
-
if (dev->bus)
-
blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);
-
kobject_uevent(&dev->kobj, KOBJ_ADD);
-
bus_probe_device(dev); //最关心的部分:匹配驱动
-
if (parent)
-
klist_add_tail(&dev->p->knode_parent,&parent->p->klist_children);
-
-
if (dev->class) {
-
mutex_lock(&dev->class->p->class_mutex);
-
klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices);
-
list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node)
-
if (class_intf->add_dev)
-
class_intf->add_dev(dev, class_intf);
-
mutex_unlock(&dev->class->p->class_mutex);
-
}
-
}
2.2 bus_probe_device
platform_add_devices ;add多个devices
--> platform_device_add ;add单个devices
--> device_add
--> bus_probe_device ;匹配驱动
-
void bus_probe_device(struct device *dev)
-
{
-
struct bus_type *bus = dev->bus;
-
if (bus && bus->p->drivers_autoprobe) {
-
device_attach(dev);
-
}
-
}
2.3 device_attach
platform_add_devices ;add多个devices
--> platform_device_add ;add单个devices
--> device_add
--> bus_probe_device ;匹配驱动
--> device_attach
如果己经指定了驱动就直接device_bind_driver
如果没有指定驱动,对bus上所有的驱动查找并匹配驱动
-
int device_attach(struct device *dev)
-
{
-
device_lock(dev);
-
if (dev->driver) {
-
if (klist_node_attached(&dev->p->knode_driver)) {
-
ret = 1;
-
goto out_unlock;
-
}
-
ret = device_bind_driver(dev);
-
if (ret == 0)
-
ret = 1;
-
else {
-
dev->driver = NULL;
-
ret = 0;
-
}
-
} else {
-
pm_runtime_get_noresume(dev);
-
//对注册进bus的所有驱动匹配device,会调用bus的platform_match
-
//匹配过程很简单比较name-->strcmp(pdev->name, drv->name) == 0,说明匹配成功.
-
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
-
pm_runtime_put_sync(dev);
-
}
-
out_unlock:
-
device_unlock(dev);
-
return ret;
-
}
二. platform_driver_register的过程
1. 在驱动中调用platform_driver_register注册驱动
以dm9000的注册为例,在driver/net/dm9000.c中
-
static struct platform_driver dm9000_driver = {
-
.driver = {
-
.name = "dm9000",
-
.owner = THIS_MODULE,
-
.pm = &dm9000_drv_pm_ops,
-
},
-
.probe = dm9000_probe,
-
.remove = __devexit_p(dm9000_drv_remove),
-
};
-
-
static int __init dm9000_init(void)
-
{
-
return platform_driver_register(&dm9000_driver);
-
}
2. platform_driver的注册过程
在driver/base/platform.c中
-
int platform_driver_register(struct platform_driver *drv)
-
{
-
drv->driver.bus = &platform_bus_type;
-
if (drv->probe)
-
drv->driver.probe = platform_drv_probe;
-
if (drv->remove)
-
drv->driver.remove = platform_drv_remove;
-
if (drv->shutdown)
-
drv->driver.shutdown = platform_drv_shutdown;
-
-
return driver_register(&drv->driver);
-
}
platform_driver_register
--> driver_register
在drivers/base/driver.c中
-
int driver_register(struct device_driver *drv)
-
{
-
struct device_driver *other;
-
//看一下驱动是否己被加载过,如果有,打钱"Driver name is already registered"
-
other = driver_find(drv->name, drv->bus);
-
bus_add_driver(drv); //向总线中添加驱动
-
driver_add_groups(drv, drv->groups);
-
}
-
platform_driver_register
--> driver_register
--> bus_add_driver
在drivers/base/bus.c中
-
int bus_add_driver(struct device_driver *drv)
-
{
-
struct bus_type *bus;
-
struct driver_private * priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-
klist_init(&priv->klist_devices, NULL, NULL);
-
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);
-
if (drv->bus->p->drivers_autoprobe)
-
driver_attach(drv); //向总线中添加驱动
-
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
-
module_add_driver(drv->owner, drv);
-
error = driver_create_file(drv, &driver_attr_uevent);
-
error = driver_add_attrs(bus, drv);
-
if (!drv->suppress_bind_attrs) {
-
add_bind_files(drv);
-
}
-
-
kobject_uevent(&priv->kobj, KOBJ_ADD);
-
return 0;
-
}
platform_driver_register
--> driver_register
--> bus_add_driver
--> driver_attach
在drivers/base/dd.c中
-
int driver_attach(struct device_driver *drv)
-
{
-
//遍历总线上的所有设备,调用__driver_attach匹配driver
-
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
-
}
platform_driver_register
--> driver_register
--> bus_add_driver
--> driver_attach
--> __driver_attach
这个函数很关键,即有驱动与设备的匹配过程,又调用了驱动的probe函数
-
static int __driver_attach(struct device *dev, void *data)
-
{
-
struct device_driver *drv = data;
-
//如果drv->bus->match存在就调用来匹配drv与dev,匹配不成功则返回
-
//注意这个返回值(strcmp(a,b)==0),匹配成功返回1,不成功返回0
-
if (!driver_match_device(drv, dev))
-
return 0;
-
if (dev->parent)
-
device_lock(dev->parent);
-
device_lock(dev);
-
if (!dev->driver)
-
driver_probe_device(drv, dev); //驱动与设备匹配成功后就会调用驱动的probe函数
-
device_unlock(dev);
-
if (dev->parent)
-
device_unlock(dev->parent);
-
return 0;
-
}
2.1 驱动匹配设备的过程
platform_driver_register
--> driver_register
--> bus_add_driver
--> driver_attach
--> __driver_attach
--> drvier_match_device
-
static inline int driver_match_device(struct device_driver *drv, struct device *dev)
-
{
-
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
-
}
在
platform_driver_register函数中有
drv->driver.bus = &platform_bus_type;
-
struct bus_type platform_bus_type = {
-
.name = "platform",
-
.dev_attrs = platform_dev_attrs,
-
.match = platform_match,
-
.uevent = platform_uevent,
-
.pm = &platform_dev_pm_ops,
-
};
在driver/base/platform.c中
-
static int platform_match(struct device *dev, struct device_driver *drv)
-
{
-
struct platform_device *pdev = to_platform_device(dev);
-
struct platform_driver *pdrv = to_platform_driver(drv);
-
-
if (of_driver_match_device(dev, drv))
-
return 1;
-
if (pdrv->id_table) //如果有id_table,驱动可以支持多个设备
-
return platform_match_id(pdrv->id_table, pdev) != NULL;
-
-
return (strcmp(pdev->name, drv->name) == 0); //还是strcmp
-
}
id_table的解析过程
-
static const struct platform_device_id *platform_match_id(
-
const struct platform_device_id *id,
-
struct platform_device *pdev)
-
{
-
while (id->name[0]) {
-
if (strcmp(pdev->name, id->name) == 0) { //还是strcmp
-
pdev->id_entry = id;
-
return id;
-
}
-
id++;
-
}
-
return NULL;
-
}
2.2 调用驱动程序probe的过程
platform_driver_register
--> driver_register
--> bus_add_driver
--> driver_attach
--> __driver_attach
其中的参数drv与dev是匹配成功的两个drv与dev
在drivers/base/dd.c中
-
int driver_probe_device(struct device_driver *drv, struct device *dev)
-
{
-
int ret = 0;
-
if (!device_is_registered(dev))
-
return -ENODEV;
-
-
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
-
drv->bus->name, __func__, dev_name(dev), drv->name);
-
-
pm_runtime_get_noresume(dev);
-
pm_runtime_barrier(dev);
-
ret = really_probe(dev, drv); //really_probe,这名字起得,莫非以前都在玩我吗?
-
pm_runtime_put_sync(dev);
-
-
return ret;
-
}
真的要调用probe了
在drivers/base/dd.c中
-
static int really_probe(struct device *dev, struct device_driver *drv)
-
{
-
atomic_inc(&probe_count);
-
dev->driver = drv;
-
driver_sysfs_add(dev);
-
if (dev->bus->probe)
-
ret = dev->bus->probe(dev);
-
else if (drv->probe)
-
ret = drv->probe(dev); //终于要调用驱动的probe了,传给probe的参数是匹配的设备
-
driver_bound(dev);
-
}
三. 总结
1. 不论注册device还是注册driver都会遍历bus对其中的driver或device进行匹配
2. 驱动调用了platform_device_register之后会调用驱动的probe函数.
阅读(2480) | 评论(0) | 转发(0) |