为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表

1. 代码流程(drivers/base/dd.c)

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第1张图片

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第2张图片

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第3张图片

可以看到在probe失败的时候(驱动返回-EPROBE_DEFER)是把设备挂到deferred_probe_pending_list上面的。

这就带来了一个疑问: 我当前明明是驱动加载的过程(driver_attach()->bus_for_each_dev()), 为什么要将设备挂到pending list上面而不是将驱动挂在pending list上面?

2. 作者是怎么说的

drivercore: Add driver probe deferral mechanism · torvalds/linux@d1c3414 · GitHub

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第4张图片

从上面的截图看出,作者也是认为"如果要求的资源暂不可得,那么驱动通过在probe返回-EPROBE_DEFER这种方式请求延迟probe调用……",驱动这一行为的结果导致了dev被加入到pending list中去。

为什么是dev而不是drv,这一点没说清楚。

3. 猜测

一共有两种场景:

场景一: device_attach()->__device_attach()->bus_for_each_drv()->__device_attach_driver()->driver_probe_device()->really_probe()

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第5张图片

这种情况是驱动先注册,设备后注册,对要注册的设备,遍历总线上所有的驱动尝试进行匹配,如果probe出现问题,将设备挂入链表,进行延迟probe,没有问题。

需要注意的是按照linux下的设备驱动模型,一个设备只能匹配一个驱动,所以此时probe根本没有成功。

场景二: driver_attach()->bus_for_each_dev()->__driver_attach()->device_driver_attach()->driver_probe_device()->really_probe()

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第6张图片

这种情况是设备先注册,驱动后注册,对要注册的驱动,遍历总线上的所有设备尝试进行匹配。

需要注意的是按照linux下的设备驱动模型,一个驱动可以匹配多个设备,如果某个probe出问题,用某种方法将驱动挂入链表尝试后续进行延迟probe则会出现问题: 假如dev0,dev1都能匹配drv,恰恰是与dev1匹配时probe出了问题,如果选择延迟probe的话,dev0、dev1都要调一次probe,而我们的期望是dev1与驱动匹配的时候只调一次probe就可以了。

所以说综上所述,选择将设备挂入延迟链表是最佳的,既能兼容驱动先注册/驱动后注册的场景,又因为设备与驱动的唯一匹配性,避免发生问题。

4. 资料

Documentation/driver-api/driver-model/binding.rst

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第7张图片

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第8张图片

为什么deferred probe将设备挂入延迟链表而不是将驱动挂入延迟链表_第9张图片

 

你可能感兴趣的:(驱动开发)