pci_enable_device() 在 remove/rescan 之后失败

pci_enable_device() fails after remove/rescan

我这里有 Linux 4.4(我曾经在一个旧内核上工作,它以同样的方式失败)带有一个 PCIe 连接的 FPGA 设备和一个驱动程序,它们都是我自己设计的。这些在正常条件下一直运行良好,但现在我尝试让它们在热插拔条件下工作。这不是真正的硬件热插拔,我一直在尝试的是设备的 sysfs 目录中通常的 echo 1 >remove 和之后的 echo 1 >/sys/bus/pci/rescan

设备重新出现后,我的驱动程序的初始化调用 pci_enable_device() 在记录时失败了:

otscan 0000:02:00.0: can't enable device: BAR 0 [mem 0xf7e01000-0xf7e013ff] not claimed
otscan 0000:02:00.0: can't enable device: BAR 1 [mem 0xf7e00000-0xf7e00fff] not claimed
otscan 0000:02:00.0: can't enable device: BAR 2 [mem 0xf0200000-0xf020ffff 64bit pref] not claimed

(通常它会在第一个无人认领的资源后停止,但我已经修改它继续并确认实际上所有 BAR 都无人认领。)

"Not claimed" 这里的意思是 struct resource 存在但没有父级,据我所知,这是由于 request_resource() 从未被调用过造成的。我不认为这是一个驱动程序问题,因为初始化例程在由于未能启用设备而中止之前没有做很多事情。

这留下了 FPGA(具有硬 IP PCIe 内核的 Altera Cyclone V)和我可能在那里做错的事情,例如以某种方式错误处理总线重置。当通过 sysfs 重新插入时,该计算机中的其他 PCIe 设备可以工作。

我已经研究了一段时间,但仍然没有弄清楚 Linux 为什么我的设备受到不同对待。我的设备 属性 有什么可能 Linux 决定不在我设备的 BAR 上调用 request_resource()

看来找到原因了。我在 PCIe 核心配置中将 class 代码保留为 0(无效),当设备在启动时出现时它工作正常。输入一个合理的值(0x40000 用于多媒体视频设备,0xff0000 用于 "unregistered device" 也有效)也使它在热插拔上工作。

看来 Linux 只能部分处理带有 0 class 代码的设备。

问题似乎是在 FPGA 的 PCIe Core 的 PCIe 配置 space 中 class 定义不正确。确保 CLASS REGISTER 的高字节是 st 不同于 0

我们在查看 dmesg 时遇到了类似的问题: "can't enable device: BAR 0 ... ... not claimed" 其次是 "pci_enable_device failed"

确实是class代码设置不正确。我建议设置 0x058000 对应一个内存控制器。