Linux驱动probe函数调用

转自:http://blog.csdn.net/wbcuc/article/details/8618363

 

参考:

http://blog.chinaunix.net/space.php?uid=15887868&do=blog&id=2758294

http://www.cnblogs.com/hoys/archive/2011/04/01/2002299.html
1,driver_register把驱动注册到总线

  1. /**
  2. * driver_register - register driver with bus
  3. * @drv: driver to register
  4. * We pass off most of the work to the bus_add_driver() call,
  5. * since most of the things we have to do deal with the bus
  6. * structures.
  7. */ 
  8. int driver_register(struct device_driver *drv) 
  9. …………………… 
  10.     if ((drv->bus->probe && drv->probe) || 
  11.         (drv->bus->remove && drv->remove) || 
  12.         (drv->bus->shutdown && drv->shutdown)) 
  13.  
  14.     ret = bus_add_driver(drv);//把drv驱动,注册到总线 
  15. …………………… 
/**
 * 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.
 */
int driver_register(struct device_driver *drv)
{
……………………
	if ((drv->bus->probe && drv->probe) ||
	    (drv->bus->remove && drv->remove) ||
	    (drv->bus->shutdown && drv->shutdown))

	ret = bus_add_driver(drv);//把drv驱动,注册到总线
……………………
}


2,驱动注册到总线的实现函数

  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.     if (drv->bus->p->drivers_autoprobe) { 
  8.         error = driver_attach(drv);      //驱动的匹配函数 
  9. ……………… 
/**
 * bus_add_driver - Add a driver to the bus.        -----在总线上加入一个驱动
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
………………
	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);      //驱动的匹配函数
………………
}

3,driver_attach()

  1. /**
  2. * driver_attach - try to bind driver to devices.
  3. * @drv: driver.
  4. *
  5. * Walk the list of devices that the bus has on it and try to
  6. * match the driver with each one.  If driver_probe_device()
  7. * returns 0 and the @dev->driver is set, we've found a
  8. * compatible pair.
  9. */ 
  10. int driver_attach(struct device_driver *drv) 
  11.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);//注意这里的__driver_attach 
  12. EXPORT_SYMBOL_GPL(driver_attach); 
/**
 * 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);//注意这里的__driver_attach
}
EXPORT_SYMBOL_GPL(driver_attach);

上面真正起作用的是__driver_attach:

  1. static int __driver_attach(struct device *dev, void *data) 
  2.     struct device_driver *drv = data; 
  3.  
  4.     /*
  5.      * Lock device and try to bind to it. We drop the error
  6.      * here and always return 0, because we need to keep trying
  7.      * to bind to devices and some drivers will return an error
  8.      * simply if it didn't support the device.
  9.      *
  10.      * driver_probe_device() will spit a warning if there
  11.      * is an error.
  12.      */ 
  13.  
  14.     if (!driver_match_device(drv, dev)) 
  15.         return 0; 
  16.  
  17.     if (dev->parent) /* Needed for USB */ 
  18.         device_lock(dev->parent); 
  19.     device_lock(dev); 
  20.     if (!dev->driver) 
  21.         driver_probe_device(drv, dev);//看下这个函数的实现过程 
  22.     device_unlock(dev); 
  23.     if (dev->parent) 
  24.         device_unlock(dev->parent); 
  25.  
  26.     return 0; 
  27. int driver_probe_device(structdevice_driver *drv, struct device *dev) 
  28. ... 
  29. //1.先是判断bus是否match: 
  30. if (drv->bus->match && !drv->bus->match(dev, drv)) 
  31.    goto done; 
  32. //2.再具体执行probe: 
  33. ret = really_probe(dev, drv); 
  34. ... 
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 (!driver_match_device(drv, dev))
		return 0;

	if (dev->parent)	/* Needed for USB */
		device_lock(dev->parent);
	device_lock(dev);
	if (!dev->driver)
		driver_probe_device(drv, dev);//看下这个函数的实现过程
	device_unlock(dev);
	if (dev->parent)
		device_unlock(dev->parent);

	return 0;
}
int driver_probe_device(structdevice_driver *drv, struct device *dev)
{
...
//1.先是判断bus是否match:
if (drv->bus->match && !drv->bus->match(dev, drv))
   goto done;
//2.再具体执行probe:
ret = really_probe(dev, drv);
...
}

4,really_probe是我们真正要找的函数

  1. static int really_probe(struct device *dev, struct device_driver *drv) 
  2. …………………… 
  3. //1.先是调用的驱动所属总线的probe函数: 
  4.     if (dev->bus->probe) { 
  5.         ret = dev->bus->probe(dev); 
  6.         if (ret) 
  7.             goto probe_failed; 
  8.     }  
  9. //2.再调用的驱动中的probe函数: 
  10.     else if (drv->probe) { 
  11.         ret = drv->probe(dev); 
  12.         if (ret) 
  13.             goto probe_failed; 
  14.     } 
  15.  
  16.     driver_bound(dev); 
  17.     ret = 1; 
  18.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n"
  19.          drv->bus->name, __func__, dev_name(dev), drv->name);//这个信息可以看到我们注册的总 驱动、设备和总线  信息 
  20.     goto done; 
  21. ……………… 
static int really_probe(struct device *dev, struct device_driver *drv)
{
……………………
//1.先是调用的驱动所属总线的probe函数:
	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} 
//2.再调用的驱动中的probe函数:
	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_name(dev), drv->name);//这个信息可以看到我们注册的总 驱动、设备和总线  信息
	goto done;
………………
}

5.drv->bus->match(dev, drv)

driver_probe_device(struct device_driver *drv, struct device *dev)会通过drv->bus->match()来匹配PCIE设备与相应的设备驱动。对于内核为2.6.27的bus驱动“pci_express”来说,是通过调用pcie_port_bus_match()实现驱动match的。

  1. static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) 
  2.     struct pcie_device *pciedev; 
  3.     struct pcie_port_service_driver *driver; 
  4.  
  5.     if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) 
  6.         return 0; 
  7.      
  8.     pciedev = to_pcie_device(dev); 
  9.     driver = to_service_driver(drv); 
  10.     if (   (driver->id_table->vendor != PCI_ANY_ID &&  
  11.         driver->id_table->vendor != pciedev->id.vendor) || 
  12.            (driver->id_table->device != PCI_ANY_ID && 
  13.         driver->id_table->device != pciedev->id.device) ||  
  14.            (driver->id_table->port_type != PCIE_ANY_PORT && 
  15.         driver->id_table->port_type != pciedev->id.port_type) || 
  16.         driver->id_table->service_type != pciedev->id.service_type ) 
  17.         return 0;  
  18.          // driver与pciedev的id_table匹配成功,才match成功; 
  19.     return 1; 
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
{
	struct pcie_device *pciedev;
	struct pcie_port_service_driver *driver;

	if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
		return 0;
	
	pciedev = to_pcie_device(dev);
	driver = to_service_driver(drv);
	if (   (driver->id_table->vendor != PCI_ANY_ID && 
		driver->id_table->vendor != pciedev->id.vendor) ||
	       (driver->id_table->device != PCI_ANY_ID &&
		driver->id_table->device != pciedev->id.device) ||	
	       (driver->id_table->port_type != PCIE_ANY_PORT &&
		driver->id_table->port_type != pciedev->id.port_type) ||
		driver->id_table->service_type != pciedev->id.service_type )
		return 0; 
         // driver与pciedev的id_table匹配成功,才match成功;
	return 1;
}
  1. // id_table的结构定义如下,match时只关注vendor,device,port_type,service_type 
  2. struct pcie_port_service_id { 
  3.     __u32 vendor, device;       /* Vendor and device ID or PCI_ANY_ID*/ 
  4.     __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ 
  5.     __u32 class, class_mask;    /* (class,subclass,prog-if) triplet */ 
  6.     __u32 port_type, service_type;  /* Port Entity */ 
  7.     kernel_ulong_t driver_data; 
  8. }; 
// id_table的结构定义如下,match时只关注vendor,device,port_type,service_type
struct pcie_port_service_id {
	__u32 vendor, device;		/* Vendor and device ID or PCI_ANY_ID*/
	__u32 subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
	__u32 class, class_mask;	/* (class,subclass,prog-if) triplet */
	__u32 port_type, service_type;	/* Port Entity */
	kernel_ulong_t driver_data;
};

打印出的驱动设备信息如:

………………

[    0.588087] bus: 'platform': really_probe: bound device power.0to driverpower  //总线:platform  设备:power.0  驱动:power
[    0.661226] bus: 'platform': really_probe: bound device s3c24xx-pwm.0 to driver s3c24xx-pwm
[    0.678552] bus: 'platform': really_probe: bound device s3c24xx-pwm.1 to driver s3c24xx-pwm
[    0.695971] bus: 'platform': really_probe: bound device s3c24xx-pwm.2 to driver s3c24xx-pwm
[    0.713389 bus: 'platform': really_probe: bound device s3c24xx-pwm.3 to driver

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值