我这里有 Linux 4.4(我曾经在一个旧内核上工作,它以同样的方式失败)带有一个 PCIe 连接的 FPGA 设备和一个驱动程序,它们都是我自己设计的。这些在正常条件下运行良好,但现在我尝试使它们在热插拔条件下工作。这不是真正的硬件热插拔,我一直在尝试的是通常的 echo 1 >remove
在设备的 sysfs 目录和 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 都无人认领。)
这里的“未声明”是指
struct resource
存在但没有父级,从我收集的信息来看,这是由 request_resource()
引起的从来没有被调用过。我不认为这是驱动程序问题,因为初始化例程在由于无法启用设备而中止之前不会做很多事情。这留下了 FPGA(具有硬 IP PCIe 内核的 Altera Cyclone V)以及我可能在那里做错的事情,例如以某种方式错误处理总线重置。当通过 sysfs 重新插入时,该计算机中的其他 PCIe 设备可以工作。
我已经研究了一段时间,但仍然没有弄清楚为什么我的设备被 Linux 区别对待。我的设备有哪些可能的属性可以让 Linux 决定不调用
request_resource()
在我设备的 BAR 上?
最佳答案
看起来我找到了原因。我已将类(class)代码保留为 0
(这是无效的)在 PCIe 核心配置中,当设备在启动时工作正常。输入一个合理的值(在我的案例中为多媒体视频设备 0x40000
,对于“未注册设备”的 0xff0000
也有效)也使其适用于热插拔。
Linux 似乎只部分处理带有 0
的设备类(class)代码。
关于linux-kernel - 删除/重新扫描后 pci_enable_device() 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46476844/