如何强制Linux内核枚举PCI-e总线?

26

Linux内核2.6

我有一个通过GPIO加载到运行Linux的开发板上的fpga。该fpga将通过PCI Express总线传输和接收数据。但是,这在启动时进行枚举,因此不会发现连接(因为fpga未在启动时加载)。

我如何强制重新枚举Linux中的PCI Express总线?有简单的命令还是必须进行内核更改?我需要具备热插拔PCIe设备的功能。


设备驱动程序不应该负责处理这个吗? - Ignacio Vazquez-Abrams
不,看起来pci-e驱动程序只会在启动时自动枚举设备,如果在启动后插入设备,则什么也不会发生。 lspci不显示任何设备,也不存在设备文件。 - reign_man
1
我认为答案是“不”,尽管我很愿意错。Altera似乎有一种解决方法,请在Google上搜索“通过协议配置Altera FPGA”。如果我正确理解了这篇论文,Altera在某些Stratix V设备中提供了可用于PCIe总线枚举的闪存,而FPGA的大部分可以在闲暇时进行(重新)编程。 - David Pointer
以下是一个最小的QEMU示例,可供测试使用:https://dev59.com/qW445IYBdhLWcg3wDWGc#44739823 - Ciro Santilli OurBigBook.com
3个回答

27

这似乎是一个简单的解决方案,但我可以想象如果这导致PCI总线离线一两秒钟,它可能会使您的PCI设备/驱动程序出现问题。 - Chris Desjardins
如果您需要使用 sudo,则会出现 "permission denied" 的错误。在这种情况下,请使用 sudo sh -c "echo 1 > /sys/bus/pci/rescan" - mivk
2
更简单的方法:echo 1 | sudo tee /sys/bus/pci/rescan - Mark Rose
4
重新扫描之前,需通过将1写入/sys/bus/pci/devices/.../remove来移除卡的Linux驱动程序知识。 - vrdhn
我们在使用Xilinx和Altera FPGAs以及内核版本3.8或更高版本时使用此方法,包括上述步骤2:echo 1 > /sys/bus/pci/devices/$device/remove。 - Jamey Hicks
显示剩余3条评论

12
我想知道你使用的平台是什么:对于x86系统,一种解决方法(也称为hack)是让BIOS在FPGA通常所在的总线、设备和功能上静态地配置一个PCI设备,然后操作系统将枚举该设备并为其保留PCI空间(即使实际上该设备不存在)。然后,在设备驱动程序中,您需要手动设置一些额外的内容,例如在fpga编程完成后手动设置BAR和int lines。当然,这需要修改BIOS,如果您正在与BIOS供应商合作,您可以要求他们为您进行此更改,如果您没有与BIOS供应商合作,那么这将会更加困难...另外请注意,我是在x86上使用VxWorks,并且我们有AMI为我们的板卡制作了定制BIOS...

如果您没有BIOS,则考虑在引导加载程序中进行编程,您已经具备了从磁盘读取的能力,并且添加GPIO能力可能并不太困难(假设您使用的是jtag和GPIO?),事实上,根据您使用的引导加载程序,它可能已经能够执行GPIO?

修改内核的问题是您必须找到一个甜点,在此之前您可以读取位文件,而不是PCI枚举...例如,如果磁盘设备驱动程序在PCI之后初始化,则显然您必须对内核进行一些根本性的更改,以便在PCI枚举之前读取位文件,这可能会引起其他烦人的问题...

另一个选项是在开发时间内使用:启动系统,编程FPGA板,然后重置(不用重新上电,例如:sudo reboot now),FPGA应该保持其配置,而Linux应该将其枚举...


重启循环是我们目前正在进行的操作。这是一个Marvell ARM平台,作为Altera Arria II fpga的控制板。 - reign_man
我也在想,可能可以修改内核,使其在枚举之前加载fpga。我不确定这是否可行/可能。 - reign_man
关于引导加载程序修改的另一件事:如果您的引导加载程序不支持现场升级,请在发布之前考虑添加复杂功能的后果...或者考虑采用使其支持现场升级的方法。 - Chris Desjardins

7
打开计算机后,BIOS会枚举PCI总线并尝试满足所有IO空间和内存映射IO(MMIO)请求。它最初设置这些BAR,当操作系统加载时,这些BAR可以根据操作系统的需要随意更改,而PCI总线驱动程序再次枚举总线。甚至可能会出现超级用户在BIOS已尝试配置它们并且操作系统已加载后运行命令setpci来更改这些BAR的情况(如果不正确执行可能导致驱动程序失败和其他许多问题)。
在某些情况下,我不得不这样做,因为该卡未被BIOS分配任何资源,因为所需的区域需要64位地址,而BIOS仅使用32位地址分配。我能够事后更改这些地址(由BIOS最初分配),插入内核模块,我的驱动程序将映射并使用这些新分配的地址用于该卡,而不知道差异。
PCI-Express卡热插拔存在的问题在于,插槽本身的电源无法打开/关闭,除非主板/背板上存在特定的热插拔控制器。如果没有这些热插拔控制器来关闭插槽的电源,如果仍有电源,则插入和/或移除卡时可能会导致微小引脚之间的短路。但是,可以通过主机或端点设备启动热插拔事件。然而,如果您的FPGA已经与根复杂结构建立了链接,则解决问题的一个可能方法是生成热插拔中断以在操作系统中引起总线重新扫描。
然而,存在一个重大问题-如果您的卡实际上没有与根复杂结构建立链接,则无法生成任何热插拔事件;这似乎就是情况。启动后,FPGA应切换PCIe总线上的PRESENT线以告诉操作系统有一张卡准备好被枚举。检测到后,操作系统应尝试建立与该卡的链接并为设备分配存储器区域。操作系统枚举卡后,您将能够针对其加载驱动程序并在lspci中看到它。您提到使用内核2.6,该内核支持热插拔和动态资源分配,因此只要您的FPGA也支持切换PRESENT PCIe线的功能,此方法就应该适用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接