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
对应一个内存控制器。
我这里有 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
对应一个内存控制器。