Linux 内核 PCI:pci_dev 是如何与 driver 建立绑定的(match / probe 双路径)

本文接续 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~1099PCI 新枚举的 pci_dev 走这里——bus_for_each_drv 沿 pci_bus_typeklist_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 /* no match */
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 } /* ret > 0 means positive match */
...
1024 ret = driver_probe_device(drv, dev);
  • 996driver_match_device 是内联薄封装,最终调 dev->bus->match(dev, drv)
  • 1024:一旦匹配上,进 driver_probe_devicereally_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_devicedrivers/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 /* When driver_override is set, only bind to the matching driver */
144 ret = device_match_driver_override(&dev->dev, &drv->driver);
145 if (ret == 0)
146 return NULL;
147
148 /* Look at the dynamic ids first, before the static ones */
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 /* driver_override will always match, send a dummy id */
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_devicereally_probe 最后调 bus->probe,即 pci_device_probedrivers/pci/pci-driver.c:473);它再走 __pci_device_probedrivers/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_probenvme_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 /* The (void *) will be put back to const * in __driver_attach() */
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) // 加进 bus->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_addbus_probe_device 拿 dev 遍历 bus->drivers __device_attach_driverdd.c:989 driver_match_devicepci_bus_matchpci-driver.c:1536)→ driver_probe_devicepci_device_probepci-driver.c:473)→ drv->probe
驱动到(modprobe / built-in init) driver_registerbus_add_driverbus.c:732 拿 drv 遍历 bus->devices __driver_attachdd.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
# 1) 解绑原驱动
echo 0000:81:00.0 > /sys/bus/pci/drivers/ixgbe/unbind

# 2) 设置 driver_override
echo vfio-pci > /sys/bus/pci/devices/0000:81:00.0/driver_override

# 3) 触发一次匹配
echo 0000:81:00.0 > /sys/bus/pci/drivers_probe
# 或者:echo 0000:81:00.0 > /sys/bus/pci/drivers/vfio-pci/bind

0.11.2. 内部机制

  1. unbinddevice_release_driverdev->driver 清成 NULL,ixgbe_remove 跑一遍。
  2. driver_override:只是把 pdev->driver_override 字符串设成 "vfio-pci"不改 dev->driver
  3. drivers_probebind:走的还是 __device_attach(或 device_driver_attach)→ bus_for_each_drvpci_bus_matchpci_match_device

关键在 pci_match_devicepci-driver.c:136)第 144 行的 device_match_driver_override

  • 若 drv 名不是 "vfio-pci",直接返回 NULL(ret == 0)——其他驱动全部被拒,哪怕 id_table 匹配;
  • 若 drv 就是 vfio-pciret > 0;vfio-pci 自身没有静态 id_table(它是”通用直通壳子”),走到函数末尾 178~179 行 return &pci_device_id_any 拿到一个”哑 id” 让 match 通过。

0.11.3. 结论

  • 不走 __device_attach 1076 那条 “dev->driver 已被预置” 的分支。
  • 走的还是同一条 __device_attachbus_for_each_drvpci_bus_match 主路径。
  • driver_overridepci_match_device 内部起过滤器作用——把匹配范围强行收窄到”驱动名 == override 字符串”这一个候选,其余全 pass。

pci_bus_type 声明中的 .driver_override = truepci-driver.c:1728)就是打开这个机制的总开关。


0.12. 十二、小结

  1. device_add(&dev->dev) 之后的完整语义是:bus_probe_devicedevice_initial_probe(受 drivers_autoprobe 控制)→ __device_attach → 遍历 pci_bus_type当前已注册的每个 pci_driver,通过 pci_bus_match 判断是否命中;命中即经 driver_probe_devicereally_probepci_device_probedrv->probe(pdev, id)
  2. 与之对偶的 pci_register_driverdriver_attach__driver_attach驱动侧发起的补绑路径,两者最终汇合到同一个 really_probe
  3. pci_match_device 内部按 driver_overridedynidsid_table 的优先级做匹配;PCI_ANY_ID 视为通配。
  4. VFIO 直通不是”预置 dev->driver“,而是通过 driver_override 把匹配收窄到 vfio-pci 一个候选。
  5. 若命中失败(没装/没加载对应驱动),pci_dev 就”就位”等待——ueventMODALIAS 会驱动用户态 udev/kmod 触发 modprobe,加载后由路径 B 回补 probe。这条用户态链条见下一篇。

0.13. 参考


Linux 内核 PCI:pci_dev 是如何与 driver 建立绑定的(match / probe 双路径)
https://martinbj2008.github.io/2026/07/09/2026-07-09-pci-dev-bind-driver.ai/
Author
Martinbj2008
Posted on
July 9, 2026
Licensed under