本文接续 Linux 内核 PCI 枚举:pci_scan_slot 及其调用链梳理 ,讨论 pci_device_add() 末尾那一句 device_add(&dev->dev) 之后,driver core 到底做了什么,pci_dev 是如何”找到”驱动并最终跑到驱动 .probe 的。
本文中所有代码引用均基于内核 v7.2-rc2-22-g0e35b9b6ec0f 的源码。【Claude-4.7-Opus】
0.1. 一、切入点:device_add 里那一跳 drivers/base/core.c
1 2 3 4 5 6 7 8 3765 * bus_probe_device() -> device_initial_probe() -> __device_attach()3766 * will notice (under device_lock) that the device is already bound. 3767 */ 3768 device_lock (dev) ;3769 dev_set_ready_to_probe(dev);3770 device_unlock(dev);3771 3772 bus_probe_device(dev);
pci_device_add() 末尾 device_add(&dev->dev),就在这一行把 probe 链启动。3765 那条注释已经把主调用路径写死了。
0.2. 二、bus_probe_device:由 bus 决定要不要自动 probe drivers/base/bus.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 613 void bus_probe_device (struct device *dev) 614 {615 struct subsys_private *sp = bus_to_subsys(dev->bus);616 struct subsys_interface *sif ;617 618 if (!sp)619 return ;620 621 device_initial_probe(dev);622 623 mutex_lock(&sp->mutex);624 list_for_each_entry(sif, &sp->interfaces, node)625 if (sif->add_dev)626 sif->add_dev(dev, sif);627 mutex_unlock(&sp->mutex);628 subsys_put(sp);629 }
只做两件事:调 device_initial_probe 走 probe 流程;再通知所有挂在该 bus 上的 subsys_interface(PCI 一般用不上)。
0.3. 三、device_initial_probe:drivers_autoprobe 开关控制 drivers/base/dd.c
1 2 3 4 5 6 7 8 9 10 11 12 1145 void device_initial_probe (struct device *dev) 1146 {1147 struct subsys_private *sp = bus_to_subsys(dev->bus);1148 1149 if (!sp)1150 return ;1151 1152 if (sp->drivers_autoprobe)1153 __device_attach(dev, true );1154 1155 subsys_put(sp);1156 }
sp->drivers_autoprobe 对应 /sys/bus/pci/drivers_autoprobe,默认 1。运维 echo 0 关掉后(常见于 SR-IOV VF、GPU 直通场景),枚举出的 pci_dev 只挂到 bus 上、不自动绑驱动 。
0.4. 四、__device_attach:拿 dev 遍历 bus 上”已注册”的驱动 drivers/base/dd.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1068 static int __device_attach(struct device *dev, bool allow_async)1069 {1070 int ret = 0 ;1071 bool async = false ;1072 1073 device_lock(dev);1074 if (dev->p->dead) {1075 goto out_unlock;1076 } else if (dev->driver) {1077 if (device_is_bound(dev)) {1078 ret = 1 ;1079 goto out_unlock;1080 }1081 ret = device_bind_driver(dev);1082 if (ret == 0 )1083 ret = 1 ;1084 else {1085 device_set_driver(dev, NULL );1086 ret = 0 ;1087 }1088 } else {1089 struct device_attach_data data = {1090 .dev = dev,1091 .check_async = allow_async,1092 .want_async = false ,1093 };1094 1095 if (dev->parent)1096 pm_runtime_get_sync(dev->parent);1097 1098 ret = bus_for_each_drv(dev->bus, NULL , &data,1099 __device_attach_driver);
1074 :设备已 dead 直接退出。
1076~1087 :设备已经关联了一个 driver(上游代码显式 device_bind_driver 或直接 dev->driver = ... 预置过)。PCI 正常枚举路径几乎见不到,多出现在 DT 平台设备的少数 fixup 场景。
1088~1099 :PCI 新枚举的 pci_dev 走这里 ——bus_for_each_drv 沿 pci_bus_type 的 klist_drivers 遍历,对每个已注册 pci_driver 回调 __device_attach_driver。
0.5. 五、__device_attach_driver:match + probe 双动作 drivers/base/dd.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 989 static int __device_attach_driver(struct device_driver *drv, void *_data)990 {991 struct device_attach_data *data = _data;992 struct device *dev = data->dev;993 bool async_allowed;994 int ret;995 996 ret = driver_match_device(drv, dev);997 if (ret == 0 ) {998 999 return 0 ;1000 } else if (ret == -EPROBE_DEFER) {1001 dev_dbg(dev, "Device match requests probe deferral\n" );1002 dev_set_can_match(dev);1003 driver_deferred_probe_add(dev); ...1013 } ...1024 ret = driver_probe_device(drv, dev);
996 :driver_match_device 是内联薄封装,最终调 dev->bus->match(dev, drv)。
1024 :一旦匹配上,进 driver_probe_device → really_probe。
0.6. 六、pci_bus_match:真正的匹配点 drivers/pci/pci-driver.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1536 static int pci_bus_match (struct device *dev, const struct device_driver *drv) 1537 {1538 struct pci_dev *pci_dev = to_pci_dev(dev);1539 struct pci_driver *pci_drv ;1540 const struct pci_device_id *found_id ;1541 1542 if (pci_dev_binding_disallowed(pci_dev))1543 return 0 ;1544 1545 pci_drv = (struct pci_driver *)to_pci_driver(drv);1546 found_id = pci_match_device(pci_drv, pci_dev);1547 if (found_id)1548 return 1 ;1549 1550 return 0 ;1551 }
pci_match_device(drivers/pci/pci-driver.c:136)内部:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 136 static const struct pci_device_id *pci_match_device (struct pci_driver *drv, 137 struct pci_dev *dev) 138 { ...143 144 ret = device_match_driver_override(&dev->dev, &drv->driver);145 if (ret == 0 )146 return NULL ;147 148 149 spin_lock(&drv->dynids.lock);150 list_for_each_entry(dynid, &drv->dynids.list , node) {151 if (pci_match_one_device(&dynid->id, dev)) {152 found_id = &dynid->id;153 break ;154 }155 }156 spin_unlock(&drv->dynids.lock);157 158 if (found_id)159 return found_id;160 161 for (ids = drv->id_table; (found_id = pci_match_id(ids, dev));162 ids = found_id + 1 ) { ...177 178 if (ret > 0 )179 return &pci_device_id_any;180 return NULL ;181 }
匹配优先级:driver_override 过滤 → dynids(new_id 动态添加)→ 静态 id_table。按 (vendor, device, subvendor, subdevice, class) 比对,PCI_ANY_ID 视为通配。
0.7. 七、命中之后:pci_device_probe → 驱动的 .probe pci_bus_type 定义在 drivers/pci/pci-driver.c:
1 2 3 4 5 6 7 8 1726 const struct bus_type pci_bus_type = {1727 .name = "pci" ,1728 .dev_groups = pci_dev_groups,1729 .match = pci_bus_match,1730 .uevent = pci_uevent,1731 .probe = pci_device_probe, ...1743 EXPORT_SYMBOL(pci_bus_type);
driver core 侧 driver_probe_device → really_probe 最后调 bus->probe,即 pci_device_probe(drivers/pci/pci-driver.c:473);它再走 __pci_device_probe(drivers/pci/pci-driver.c:445):
1 2 3 445 static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) ...453 id = pci_match_device(drv, pci_dev);
最后 pci_call_probe 调具体驱动的 .probe(pdev, id)(如 ixgbe_probe、nvme_probe)——驱动接管设备的那一刻 :pci_enable_device、映射 BAR、注册中断、注册 netdev/blockdev……
0.8. 八、双路径:设备侧发起 vs 驱动侧发起 device_add 触发的只是”设备侧→找驱动”这一条。真正让机制闭合的,是驱动侧反向那一条。
0.8.1. 路径 A:设备侧发起(device_add 触发) 1 2 3 4 5 6 7 8 9 10 11 pci_device_add └─ device_add drivers/base/core.c :3639 └─ bus_probe_device drivers/base/bus.c :613 └─ device_initial_probe drivers/base/dd .c :1145 (受 drivers_autoprobe 控制) └─ __device_attach drivers/base/dd .c :1068 └─ bus_for_each_drv (pci_bus_type, __device_attach_driver) └─ __device_attach_driver drivers/base/dd .c :989 ├─ driver_match_device → pci_bus_match drivers/pci/pci-driver.c :1536 └─ driver_probe_device → really_probe └─ pci_device_probe → __pci_device_probe drivers/pci/pci-driver.c :473 / 445 └─ drv->probe (pdev, id)
遍历的是当前 pci_bus_type.klist_drivers 上已注册的驱动 。
0.8.2. 路径 B:驱动侧发起(pci_register_driver / modprobe 触发) drivers/base/bus.c
1 2 3 4 732 int bus_add_driver (struct device_driver *drv) ... 762 if (sp->drivers_autoprobe) {763 error = driver_attach(drv);
drivers/base/dd.c
1 2 3 4 5 1307 int driver_attach (const struct device_driver *drv) 1308 {1309 1310 return bus_for_each_dev(drv->bus, NULL , (void *)drv, __driver_attach);1311 }
1 2 3 4 5 6 7 1232 static int __driver_attach(struct device *dev, void *data) ...1247 ret = driver_match_device(drv, dev); ...1281 __device_driver_lock(dev, dev->parent);1282 driver_probe_device(drv, dev);1283 __device_driver_unlock(dev, dev->parent);
调用链:
1 2 3 4 5 6 7 8 9 10 11 12 pci_register_driver (&ixgbe_driver) └─ __pci_register_driver └─ driver_register drivers/base/driver.c └─ bus_add_driver drivers/base/bus.c :732 ├─ klist_add_tail (&priv->knode_bus, &sp->klist_drivers) └─ if (sp->drivers_autoprobe) driver_attach drivers/base/dd .c :1307 └─ bus_for_each_dev (drv->bus, __driver_attach) └─ __driver_attach drivers/base/dd .c :1232 ├─ driver_match_device → pci_bus_match └─ driver_probe_device → really_probe └─ pci_device_probe → drv->probe
反过来遍历 bus->devices——枚举时已经挂上去、但那时还没匹配到驱动 的 pci_dev,在这一刻被回补。
0.9. 九、双路径对偶表
触发点
入口
遍历方向
关键回调
汇合点
设备到(枚举 / hot-add)
device_add → bus_probe_device
拿 dev 遍历 bus->drivers
__device_attach_driver(dd.c:989)
driver_match_device → pci_bus_match(pci-driver.c:1536)→ driver_probe_device → pci_device_probe(pci-driver.c:473)→ drv->probe
驱动到(modprobe / built-in init)
driver_register → bus_add_driver(bus.c:732)
拿 drv 遍历 bus->devices
__driver_attach(dd.c:1232)
同上
0.10. 十、三个真实场景 A. 驱动 built-in(=y) :绝大多数 pci_driver 在 PCI 枚举之前就 pci_register_driver 完了。枚举到 pci_dev 时,路径 A 直接命中 → probe 在 pci_device_add 返回前同步跑完 (除非驱动声明 PROBE_PREFER_ASYNCHRONOUS)。
B. 驱动是 ko、系统装了、但还没加载 :
枚举时路径 A 遍历 bus->drivers 空手而归,dev->driver == NULL;
pci_dev 已挂在 bus->devices、/sys/bus/pci/devices/<BDF>/ 已建好;
内核发 uevent,MODALIAS=pci:v...d...sv...sd...bc...sc...i... 已在消息里;
用户态由 udev + kmod 拾起 → modprobe → ko 加载 → pci_register_driver → 路径 B 触发 → 回补 probe。
(这一段的用户态细节参见姊妹篇:Linux 驱动 ko 动态加载:uevent、udev、kmod 协作机制 )
C. 驱动根本不存在或被 blacklist :pci_dev 一直在 /sys/bus/pci/devices/ 里,lspci -k 看得到设备但 Kernel driver in use: 为空。任何时刻 insmod/modprobe 上来,走路径 B 补绑。
0.11. 十一、专题:VFIO 与 driver_override 常见误解:”vfio 是不是把 dev->driver 预先指成 vfio-pci,走 __device_attach 里 1076 那条 ‘设备已关联驱动’ 分支?”
不是。 VFIO 走的是 driver_override 机制,不是预置 dev->driver。
0.11.1. 标准直通脚本 1 2 3 4 5 6 7 8 9 echo 0000:81:00.0 > /sys/bus/pci/drivers/ixgbe/unbindecho vfio-pci > /sys/bus/pci/devices/0000:81:00.0/driver_overrideecho 0000:81:00.0 > /sys/bus/pci/drivers_probe
0.11.2. 内部机制
unbind :device_release_driver 把 dev->driver 清成 NULL,ixgbe_remove 跑一遍。
写 driver_override :只是把 pdev->driver_override 字符串设成 "vfio-pci",不改 dev->driver 。
drivers_probe 或 bind :走的还是 __device_attach(或 device_driver_attach)→ bus_for_each_drv → pci_bus_match → pci_match_device。
关键在 pci_match_device(pci-driver.c:136)第 144 行的 device_match_driver_override:
若 drv 名不是 "vfio-pci",直接返回 NULL(ret == 0)——其他驱动全部被拒 ,哪怕 id_table 匹配;
若 drv 就是 vfio-pci,ret > 0;vfio-pci 自身没有静态 id_table(它是”通用直通壳子”),走到函数末尾 178~179 行 return &pci_device_id_any 拿到一个”哑 id” 让 match 通过。
0.11.3. 结论
不走 __device_attach 1076 那条 “dev->driver 已被预置” 的分支。
走的还是同一条 __device_attach → bus_for_each_drv → pci_bus_match 主路径。
driver_override 在 pci_match_device 内部起过滤器 作用——把匹配范围强行收窄到”驱动名 == override 字符串”这一个候选,其余全 pass。
pci_bus_type 声明中的 .driver_override = true(pci-driver.c:1728)就是打开这个机制的总开关。
0.12. 十二、小结
device_add(&dev->dev) 之后的完整语义是:bus_probe_device → device_initial_probe(受 drivers_autoprobe 控制)→ __device_attach → 遍历 pci_bus_type 上当前已注册 的每个 pci_driver,通过 pci_bus_match 判断是否命中;命中即经 driver_probe_device → really_probe → pci_device_probe → drv->probe(pdev, id)。
与之对偶的 pci_register_driver → driver_attach → __driver_attach 是驱动侧发起 的补绑路径,两者最终汇合到同一个 really_probe。
pci_match_device 内部按 driver_override → dynids → id_table 的优先级做匹配;PCI_ANY_ID 视为通配。
VFIO 直通不是”预置 dev->driver“,而是通过 driver_override 把匹配收窄到 vfio-pci 一个候选。
若命中失败(没装/没加载对应驱动),pci_dev 就”就位”等待——uevent 的 MODALIAS 会驱动用户态 udev/kmod 触发 modprobe,加载后由路径 B 回补 probe。这条用户态链条见下一篇。
0.13. 参考