PCI register driver

大多数驱动程序都要实现一个probe函数,该函数在register时被调用,具体内核是如何实现的呢?下面我们以LINUX内核中Hamachi.c为例子来分析一下:

[cpp] view plain copy print ?
  1. static struct pci_driver hamachi_driver = {  
  2.     .name       = DRV_NAME,  
  3.     .id_table   = hamachi_pci_tbl,  
  4.     .probe      = hamachi_init_one,  
  5.     .remove     = __devexit_p(hamachi_remove_one),  
  6. };  
  7.   
  8. static int __init hamachi_init (void)  
  9. {  
  10. /* when a module, this is printed whether or not devices are found in probe */  
  11. #ifdef MODULE   
  12.     printk(version);  
  13. #endif   
  14.     return pci_register_driver(&hamachi_driver);  
  15. }  
  16.   
  17. static void __exit hamachi_exit (void)  
  18. {  
  19.     pci_unregister_driver(&hamachi_driver);  
  20. }  
  21.   
  22.   
  23. module_init(hamachi_init);  
  24. module_exit(hamachi_exit);  
static struct pci_driver hamachi_driver = {
	.name		= DRV_NAME,
	.id_table	= hamachi_pci_tbl,
	.probe		= hamachi_init_one,
	.remove		= __devexit_p(hamachi_remove_one),
};

static int __init hamachi_init (void)
{
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
	printk(version);
#endif
	return pci_register_driver(&hamachi_driver);
}

static void __exit hamachi_exit (void)
{
	pci_unregister_driver(&hamachi_driver);
}


module_init(hamachi_init);
module_exit(hamachi_exit);

首先,实现了一个pci_driver结构体,名为hamachi_driver,

在hamachi_init函数中,直接调用pci_register_driver,追踪该函数:

[cpp] view plain copy print ?
  1. /* 
  2.  * pci_register_driver must be a macro so that KBUILD_MODNAME can be expanded 
  3.  */  
  4. #define pci_register_driver(driver)     \   
  5.     __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)  
/*
 * pci_register_driver must be a macro so that KBUILD_MODNAME can be expanded
 */
#define pci_register_driver(driver)		\
	__pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)

发现pci_register_driver实际上是一个macro,使用宏的目的是扩展参数,实际调用的是__pci_register_driver,继续追踪:

[cpp] view plain copy print ?
  1. /** 
  2.  * __pci_register_driver - register a new pci driver 
  3.  * @drv: the driver structure to register 
  4.  * @owner: owner module of drv 
  5.  * @mod_name: module name string 
  6.  *  
  7.  * Adds the driver structure to the list of registered drivers. 
  8.  * Returns a negative value on error, otherwise 0.  
  9.  * If no error occurred, the driver remains registered even if  
  10.  * no device was claimed during registration. 
  11.  */  
  12. int __pci_register_driver(struct pci_driver *drv, struct module *owner,  
  13.               const char *mod_name)  
  14. {  
  15.     int error;  
  16.   
  17.     /* initialize common driver fields */  
  18.     drv->driver.name = drv->name;  
  19.     drv->driver.bus = &pci_bus_type;  
  20.     drv->driver.owner = owner;  
  21.     drv->driver.mod_name = mod_name;  
  22.   
  23.     if (drv->pm)  
  24.         drv->driver.pm = &drv->pm->base;  
  25.   
  26.     spin_lock_init(&drv->dynids.lock);  
  27.     INIT_LIST_HEAD(&drv->dynids.list);  
  28.   
  29.     /* register with core */  
  30.     error = driver_register(&drv->driver);  
  31.     if (error)  
  32.         return error;  
  33.   
  34.     error = pci_create_newid_file(drv);  
  35.     if (error)  
  36.         driver_unregister(&drv->driver);  
  37.   
  38.     return error;  
/**
 * __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;

	if (drv->pm)
		drv->driver.pm = &drv->pm->base;

	spin_lock_init(&drv->dynids.lock);
	INIT_LIST_HEAD(&drv->dynids.list);

	/* register with core */
	error = driver_register(&drv->driver);
	if (error)
		return error;

	error = pci_create_newid_file(drv);
	if (error)
		driver_unregister(&drv->driver);

	return error;
}

前面填充了drv->driver结构,然后调用spin_lock_init来初始化自旋锁,调用INIT_LIST_HEAD来初始化一个双向链表,核心是调用了driver_register函数,继续追踪:

[cpp] view plain copy print ?
  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.     if ((drv->bus->probe && drv->probe) ||  
  7.         (drv->bus->remove && drv->remove) ||  
  8.         (drv->bus->shutdown && drv->shutdown))  
  9.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  10.             "bus_type methods\n", drv->name);  
  11.   
  12.     other = driver_find(drv->name, drv->bus);  
  13.     if (other) {  
  14.         put_driver(other);  
  15.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  16.             "aborting...\n", drv->name);  
  17.         return -EBUSY;  
  18.     }  
  19.   
  20.     ret = bus_add_driver(drv);  
  21.     if (ret)  
  22.         return ret;  
  23.     ret = driver_add_groups(drv, drv->groups);  
  24.     if (ret)  
  25.         bus_remove_driver(drv);  
  26.     return ret;  
  27. }  
int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	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);

	other = driver_find(drv->name, drv->bus);
	if (other) {
		put_driver(other);
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}

	ret = bus_add_driver(drv);
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret)
		bus_remove_driver(drv);
	return ret;
}
该函数首先做了一些检查,实际上是重点是调用了bus_add_drvier函数,进入该函数:

[cpp] view plain copy print ?
  1. /** 
  2.  * bus_add_driver - Add a driver to the bus. 
  3.  * @drv: driver. 
  4.  */  
  5. int bus_add_driver(struct device_driver *drv)  
  6. {  
  7.     struct bus_type *bus;  
  8.     struct driver_private *priv;  
  9.     int error = 0;  
  10.   
  11.     bus = bus_get(drv->bus);  
  12.     if (!bus)  
  13.         return -EINVAL;  
  14.   
  15.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  16.   
  17.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  18.     if (!priv) {  
  19.         error = -ENOMEM;  
  20.         goto out_put_bus;  
  21.     }  
  22.     klist_init(&priv->klist_devices, NULL, NULL);  
  23.     priv->driver = drv;  
  24.     drv->p = priv;  
  25.     priv->kobj.kset = bus->p->drivers_kset;  
  26.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  27.                      "%s", drv->name);  
  28.     if (error)  
  29.         goto out_unregister;  
  30.   
  31.     if (drv->bus->p->drivers_autoprobe) {  
  32.         error = driver_attach(drv);  
  33.         if (error)  
  34.             goto out_unregister;  
  35.     }  
  36.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  37.     module_add_driver(drv->owner, drv);  
  38.   
  39.     error = driver_create_file(drv, &driver_attr_uevent);  
  40.     if (error) {  
  41.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  42.             __func__, drv->name);  
  43.     }  
  44.     error = driver_add_attrs(bus, drv);  
  45.     if (error) {  
  46.         /* How the hell do we get out of this pickle? Give up */  
  47.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  48.             __func__, drv->name);  
  49.     }  
  50.     error = add_bind_files(drv);  
  51.     if (error) {  
  52.         /* Ditto */  
  53.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  54.             __func__, drv->name);  
  55.     }  
  56.   
  57.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  58.     return error;  
  59. out_unregister:  
  60.     kobject_put(&priv->kobj);  
  61. out_put_bus:  
  62.     bus_put(bus);  
  63.     return error;  
  64. }  
/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;

	bus = bus_get(drv->bus);
	if (!bus)
		return -EINVAL;

	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
	klist_init(&priv->klist_devices, NULL, NULL);
	priv->driver = drv;
	drv->p = priv;
	priv->kobj.kset = bus->p->drivers_kset;
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);
	if (error)
		goto out_unregister;

	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	module_add_driver(drv->owner, drv);

	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	error = driver_add_attrs(bus, drv);
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
			__func__, drv->name);
	}
	error = add_bind_files(drv);
	if (error) {
		/* Ditto */
		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
			__func__, drv->name);
	}

	kobject_uevent(&priv->kobj, KOBJ_ADD);
	return error;
out_unregister:
	kobject_put(&priv->kobj);
out_put_bus:
	bus_put(bus);
	return error;
}
该函数前面还是一些分配资源和初始化的工作,直到driver_attach函数,该函数的作用是遍历总线上所有的设备,将驱动与设备绑定:

[cpp] view plain copy print ?
  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  
int driver_attach(struct device_driver *drv)
{
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}


进入bus_for_each_dev函数中,


[html] view plain copy print ?
  1. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  2.              void *data, int (*fn)(struct device *, void *))  
  3. {  
  4.     struct klist_iter i;  
  5.     struct device *dev;  
  6.     int error = 0;  
  7.   
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  12.                  (start ? &start->knode_bus : NULL));  
  13.     while ((dev = next_device(&i)) && !error)  
  14.         error = fn(dev, data);  
  15.     klist_iter_exit(&i);  
  16.     return error;  
  17. }  
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->p->klist_devices, &i,
			     (start ? &start->knode_bus : NULL));
	while ((dev = next_device(&i)) && !error)
		error = fn(dev, data);
	klist_iter_exit(&i);
	return error;
}
该函数的重点是调用了fn这个函数指针实现回调,回调函数为__driver_attach,进入该函数:

[cpp] view plain copy print ?
  1. static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.   
  5.     /* 
  6.      * Lock device and try to bind to it. We drop the error 
  7.      * here and always return 0, because we need to keep trying 
  8.      * to bind to devices and some drivers will return an error 
  9.      * simply if it didn't support the device. 
  10.      * 
  11.      * driver_probe_device() will spit a warning if there 
  12.      * is an error. 
  13.      */  
  14.   
  15.     if (dev->parent) /* Needed for USB */  
  16.         down(&dev->parent->sem);  
  17.     down(&dev->sem);  
  18.     if (!dev->driver)  
  19.         driver_probe_device(drv, dev);  
  20.     up(&dev->sem);  
  21.     if (dev->parent)  
  22.         up(&dev->parent->sem);  
  23.   
  24.     return 0;  
  25. }  
static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	/*
	 * Lock device and try to bind to it. We drop the error
	 * here and always return 0, because we need to keep trying
	 * to bind to devices and some drivers will return an error
	 * simply if it didn't support the device.
	 *
	 * driver_probe_device() will spit a warning if there
	 * is an error.
	 */

	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;
}

重点进入driver_probe_device函数,

[cpp] view plain copy print ?
  1. /** 
  2.  * driver_probe_device - attempt to bind device & driver together 
  3.  * @drv: driver to bind a device to 
  4.  * @dev: device to try to bind to the driver 
  5.  * 
  6.  * First, we call the bus's match function, if one present, which should 
  7.  * compare the device IDs the driver supports with the device IDs of the 
  8.  * device. Note we don't do this ourselves because we don't know the 
  9.  * format of the ID structures, nor what is to be considered a match and 
  10.  * what is not. 
  11.  * 
  12.  * This function returns 1 if a match is found, -ENODEV if the device is 
  13.  * not registered, and 0 otherwise. 
  14.  * 
  15.  * This function must be called with @dev->sem held.  When called for a 
  16.  * USB interface, @dev->parent->sem must be held as well. 
  17.  */  
  18. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  19. {  
  20.     int ret = 0;  
  21.   
  22.     if (!device_is_registered(dev))  
  23.         return -ENODEV;  
  24.     if (drv->bus->match && !drv->bus->match(dev, drv))  
  25.         goto done;  
  26.   
  27.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  28.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  29.   
  30.     ret = really_probe(dev, drv);  
  31.   
  32. done:  
  33.     return ret;  
  34. }  
/**
 * driver_probe_device - attempt to bind device & driver together
 * @drv: driver to bind a device to
 * @dev: device to try to bind to the driver
 *
 * First, we call the bus's match function, if one present, which should
 * compare the device IDs the driver supports with the device IDs of the
 * device. Note we don't do this ourselves because we don't know the
 * format of the ID structures, nor what is to be considered a match and
 * what is not.
 *
 * This function returns 1 if a match is found, -ENODEV if the device is
 * not registered, and 0 otherwise.
 *
 * This function must be called with @dev->sem held.  When called for a
 * USB interface, @dev->parent->sem must be held as well.
 */
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
	int ret = 0;

	if (!device_is_registered(dev))
		return -ENODEV;
	if (drv->bus->match && !drv->bus->match(dev, drv))
		goto done;

	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
		 drv->bus->name, __func__, dev->bus_id, drv->name);

	ret = really_probe(dev, drv);

done:
	return ret;
}

该函数的作用是将设备和驱动程序绑定,首先调用match函数指针,检查设备和驱动是否匹配,然后调用了really_probe,真正的probe:

[cpp] view plain copy print ?
  1. static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     atomic_inc(&probe_count);  
  6.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  7.          drv->bus->name, __func__, drv->name, dev->bus_id);  
  8.     WARN_ON(!list_empty(&dev->devres_head));  
  9.   
  10.     dev->driver = drv;  
  11.     if (driver_sysfs_add(dev)) {  
  12.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  13.             __func__, dev->bus_id);  
  14.         goto probe_failed;  
  15.     }  
  16.   
  17.     if (dev->bus->probe) {  
  18.         ret = dev->bus->probe(dev);  
  19.         if (ret)  
  20.             goto probe_failed;  
  21.     } else if (drv->probe) {  
  22.         ret = drv->probe(dev);  
  23.         if (ret)  
  24.             goto probe_failed;  
  25.     }  
  26.   
  27.     driver_bound(dev);  
  28.     ret = 1;  
  29.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  30.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  31.     goto done;  
  32.   
  33. probe_failed:  
  34.     devres_release_all(dev);  
  35.     driver_sysfs_remove(dev);  
  36.     dev->driver = NULL;  
  37.   
  38.     if (ret != -ENODEV && ret != -ENXIO) {  
  39.         /* driver matched but the probe failed */  
  40.         printk(KERN_WARNING  
  41.                "%s: probe of %s failed with error %d\n",  
  42.                drv->name, dev->bus_id, ret);  
  43.     }  
  44.     /* 
  45.      * Ignore errors returned by ->probe so that the next driver can try 
  46.      * its luck. 
  47.      */  
  48.     ret = 0;  
  49. done:  
  50.     atomic_dec(&probe_count);  
  51.     wake_up(&probe_waitqueue);  
  52.     return ret;  
  53. }  
static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = 0;

	atomic_inc(&probe_count);
	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
		 drv->bus->name, __func__, 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",
			__func__, dev->bus_id);
		goto probe_failed;
	}

	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {
		ret = drv->probe(dev);
		if (ret)
			goto probe_failed;
	}

	driver_bound(dev);
	ret = 1;
	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
		 drv->bus->name, __func__, dev->bus_id, drv->name);
	goto done;

probe_failed:
	devres_release_all(dev);
	driver_sysfs_remove(dev);
	dev->driver = NULL;

	if (ret != -ENODEV && ret != -ENXIO) {
		/* driver matched but the probe failed */
		printk(KERN_WARNING
		       "%s: probe of %s failed with error %d\n",
		       drv->name, dev->bus_id, ret);
	}
	/*
	 * Ignore errors returned by ->probe so that the next driver can try
	 * its luck.
	 */
	ret = 0;
done:
	atomic_dec(&probe_count);
	wake_up(&probe_waitqueue);
	return ret;
}

直到这里才利用drv->probe指针,该指针指向的是:

[cpp] view plain copy print ?
  1. struct device_driver {  
  2.     const char        *name;  
  3.     struct bus_type        *bus;  
  4.   
  5.     struct module        *owner;  
  6.     const char         *mod_name;    /* used for built-in modules */  
  7.   
  8.     int (*probe) (struct device *dev);  
  9.     int (*remove) (struct device *dev);  
  10.     void (*shutdown) (struct device *dev);  
  11.     int (*suspend) (struct device *dev, pm_message_t state);  
  12.     int (*resume) (struct device *dev);  
  13.     struct attribute_group **groups;  
  14.   
  15.     struct pm_ops *pm;  
  16.   
  17.     struct driver_private *p;  
  18. };  
struct device_driver {
    const char        *name;
    struct bus_type        *bus;

    struct module        *owner;
    const char         *mod_name;    /* used for built-in modules */

    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);
    struct attribute_group **groups;

    struct pm_ops *pm;

    struct driver_private *p;
};
中的probe函数指针,该结构体是需要你在register之前实现的,直到此时才
真正的调用了hamachi.c中你实现的probe函数。

你可能感兴趣的:(PCI)