PCI设备的注册过程分析(1)
R.wen
一、驱动与设备注册过程总述。
在2.6设备模型下,当一个驱动程序模块挂入内核(insmod),它会遍历所有在这个总线(BUS)上注册的设备链表,并且对每个被遍历的设备调用
match()函数,直到找到匹配的为止。第二种情况是,当一个设备被插入到系统总线上的时候(或系统初起),它会遍历枚举这个总线上的所有注册过的驱
动,并且对每个驱动调用match()函数,直到找到匹配的驱动为止。
之后,上两种情况都会调用probe函数,进行设备的初始化。
二、驱动注册过程。
首先是驱动的注册,以e100为例:
static struct pci_driver e100_driver = {
.name = DRV_NAME,
.id_table = e100_id_table,
.probe = e100_probe,
.remove = __devexit_p(e100_remove),
.shutdown = e100_shutdown,
……
};
static int __init e100_init_module(void)
{
return pci_register_driver(&e100_driver);
}
我们看到,它先初始化一个pci_driver结构,然后以这个结构为参数调用pci_register_driver(),它其实是:
static inline int __must_check pci_register_driver(struct pci_driver *driver)
{
return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
}
/**
* __pci_register_driver - register a new pci driver
* @drv: the driver structure to register
* @owner: owner module of drv
* @mod_name: module name string
*
* Adds the driver structure to the list of registered drivers.
* Returns a negative value on error, otherwise 0.
* If no error occurred, the driver remains registered even if
* no device was claimed during registration.
*/
int __pci_register_driver(struct pci_driver *drv, struct module *owner,
const char *mod_name)
{
int error;
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
drv->driver.owner = owner;
drv->driver.mod_name = mod_name;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
//是否使用多线程来进行probe
if (pci_multithread_probe)
drv->driver.multithread_probe = pci_multithread_probe;
else
drv->driver.multithread_probe = drv->multithread_probe;
spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);
/* register with core */
error = driver_register(&drv->driver); //上面是PCI驱动的注册,这里是通用设备的注册
if (error)
return error;
//在sysfs中建立文件项
error = pci_create_newid_file(drv);
if (error)
driver_unregister(&drv->driver);
return error;
}
/**
* driver_register - register driver with bus
* @drv: driver to register
*
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*
* The one interesting aspect is that we setup @drv->unloaded
* as a completion that gets complete when the driver reference
* count reaches 0.
*/
int driver_register(struct device_driver * drv)
{
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown)) {
printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
}
klist_init(&drv->klist_devices, NULL, NULL);
init_completion(&drv->unloaded);
return bus_add_driver(drv); //这个函数将驱动加入BUS链表
}
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/
int bus_add_driver(struct device_driver *drv)
{
struct bus_type * bus = get_bus(drv->bus);
int error = 0;
if (!bus)
return 0;
pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
error = kobject_set_name(&drv->kobj, "%s", drv->name);
if (error)
goto out_put_bus;
drv->kobj.kset = &bus->drivers;
if ((error = kobject_register(&drv->kobj)))
goto out_put_bus;
//将这个驱动与可能的设备捆绑起来
error = driver_attach(drv);
if (error)
goto out_unregister;
klist_add_tail(&drv->knode_bus, &bus->klist_drivers); //加入链表
module_add_driver(drv->owner, drv);
error = driver_add_attrs(bus, drv); //注册属性
……
return error;
}
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
//这是个重要的函数,它会遍历设备链表,试图匹配这个总线上的设备
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
static int __driver_attach(struct device * dev, void * data)
{
struct device_driver * drv = data;
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver) //如果设备没有匹配的驱动才会测试
driver_probe_device(drv, dev);
up(&dev->sem);
if (dev->parent)
up(&dev->parent->sem);
return 0; //总是返回0
}
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device * dev;
int error = 0;
if (!bus)
return -EINVAL;
klist_iter_init_node(&bus->klist_devices, &i,
(start ? &start->knode_bus : NULL));
while ((dev = next_device(&i)) && !error) //由于error总是0,所以会遍历整个链表
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
.uevent = pci_uevent,
.probe = pci_device_probe,
.remove = pci_device_remove,
.suspend = pci_device_suspend,
.suspend_late = pci_device_suspend_late,
.resume_early = pci_device_resume_early,
.resume = pci_device_resume,
.shutdown = pci_device_shutdown,
.dev_attrs = pci_dev_attrs,
};
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
struct stupid_thread_structure *data;
struct task_struct *probe_task;
int ret = 0;
if (!device_is_registered(dev)) //已经注册了
return -ENODEV;
if (drv->bus->match && !drv->bus->match(dev, drv))
goto done; //调用match()函数,如果不匹配,则说明这个驱动不合适这个设备,跳过这个设备。由上面的结构可以看到,这个函数是pci_bus_match
pr_debug("%s: Matched Device %s with Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->drv = drv;
data->dev = dev;
if (drv->multithread_probe) { //启动另一个线程来完成
probe_task = kthread_run(really_probe, data,
"probe-%s", dev->bus_id);
if (IS_ERR(probe_task))
ret = really_probe(data);
} else
ret = really_probe(data);
done:
return ret;
}
static int pci_bus_match(struct device *dev, struct device_driver *drv)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *pci_drv = to_pci_driver(drv);
const struct pci_device_id *found_id;
found_id = pci_match_device(pci_drv, pci_dev);
if (found_id)
return 1;
return 0; //不匹配
}
const struct pci_device_id *pci_match_device(struct pci_driver *drv,
struct pci_dev *dev)
{
struct pci_dynid *dynid;
/* Look at the dynamic ids first, before the static ones */
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) {
spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
spin_unlock(&drv->dynids.lock);
//检查静态表,这个表来自于pc_driver中的id_table域。
return pci_match_id(drv->id_table, dev);
}
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
struct pci_dev *dev)
{
if (ids) {
while (ids->vendor || ids->subvendor || ids->class_mask) {
if (pci_match_one_device(ids, dev))
return ids;
ids++;
}
}
return NULL;
}
static inline const struct pci_device_id *
pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
{
if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
(id->device == PCI_ANY_ID || id->device == dev->device) &&
(id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
(id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
!((id->class ^ dev->class) & id->class_mask))
return id;
return NULL;
}
如果上面的match成功返回,下一步则执行以下这个函数了。
static int really_probe(void *void_data)
{
struct stupid_thread_structure *data = void_data;
struct device_driver *drv = data->drv;
struct device *dev = data->dev;
int ret = 0;
atomic_inc(&probe_count);
pr_debug("%s: Probing driver %s with device %s\n",
drv->bus->name, drv->name, dev->bus_id);
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv; //将匹配的设备和驱动捆绑起来,这一步是关键
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__FUNCTION__, dev->bus_id);
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev); //执行总线的probe函数
if (ret)
goto probe_failed;
} else if (drv->probe) { //如果没有,则执行驱动的probe
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
goto done;
probe_failed:
…...
ret = 0;
done:
kfree(data);
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
由上面的结构可以看到,总线的probe是以下这个函数。
static int pci_device_probe(struct device * dev)
{
int error = 0;
struct pci_driver *drv;
struct pci_dev *pci_dev;
drv = to_pci_driver(dev->driver);
pci_dev = to_pci_dev(dev);
pci_dev_get(pci_dev);
error = __pci_device_probe(drv, pci_dev);
if (error)
pci_dev_put(pci_dev);
return error;
}
static int
__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
{
const struct pci_device_id *id;
int error = 0;
if (!pci_dev->driver && drv->probe) {
error = -ENODEV;
id = pci_match_device(drv, pci_dev); //再次检查匹配
if (id)
error = pci_call_probe(drv, pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
error = 0;
}
}
return error;
}
我们看到,总线的probe最终还是执行驱动程序提供的probe函数。至此,设备的注册过程已经完成。
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
const struct pci_device_id *id)
{
int error;
#ifdef CONFIG_NUMA
……
#endif
error = drv->probe(dev, id); //完成系统的初始化操作
#ifdef CONFIG_NUMA
……
#endif
return error;
}
声明: 转的,为了容易找到,帖过来了