1. 代码流程(drivers/base/dd.c)
可以看到在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
从上面的截图看出,作者也是认为"如果要求的资源暂不可得,那么驱动通过在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()
这种情况是驱动先注册,设备后注册,对要注册的设备,遍历总线上所有的驱动尝试进行匹配,如果probe出现问题,将设备挂入链表,进行延迟probe,没有问题。
需要注意的是按照linux下的设备驱动模型,一个设备只能匹配一个驱动,所以此时probe根本没有成功。
场景二: driver_attach()->bus_for_each_dev()->__driver_attach()->device_driver_attach()->driver_probe_device()->really_probe()
这种情况是设备先注册,驱动后注册,对要注册的驱动,遍历总线上的所有设备尝试进行匹配。
需要注意的是按照linux下的设备驱动模型,一个驱动可以匹配多个设备,如果某个probe出问题,用某种方法将驱动挂入链表尝试后续进行延迟probe则会出现问题: 假如dev0,dev1都能匹配drv,恰恰是与dev1匹配时probe出了问题,如果选择延迟probe的话,dev0、dev1都要调一次probe,而我们的期望是dev1与驱动匹配的时候只调一次probe就可以了。
所以说综上所述,选择将设备挂入延迟链表是最佳的,既能兼容驱动先注册/驱动后注册的场景,又因为设备与驱动的唯一匹配性,避免发生问题。
4. 资料
Documentation/driver-api/driver-model/binding.rst