24

Linux 内核 2.6

我有一个通过 GPIO 加载的 fpga,连接到运行 linux 的开发板。fpga 将通过 pci-express 总线发送和接收数据。但是,这是在启动时枚举的,因此没有发现任何链接(因为 fpga 未在启动时加载)。

如何在 linux 中强制重新枚举 pci-e 总线?是否有一个简单的命令或者我必须进行内核更改?我需要热插拔 pcie 设备的能力。

4

3 回答 3

26

以 root 身份尝试以下命令:

echo "1" > /sys/bus/pci/rescan

有关更多信息,请参阅此链接:http: //www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci

于 2012-09-14T11:38:01.410 回答
11

我想知道你在什么平台上:在 x86 系统上工作的解决方法(又名 hack)是让 BIOS 在任何总线、设备、FPGA 通常登陆的功能上基本上静态配置 PCI 设备,然后操作系统将枚举设备并为其保留 PCI 空间(即使该设备实际上并不存在)。然后在您的设备驱动程序中,您将不得不做一些额外的事情,例如在对 fpga 进行编程后手动设置 BAR 和 int 行。当然,这需要修改 BIOS,如果您与 BIOS 供应商合作,您可以与他们签订合同为您进行此更改,如果您不与 BIOS 供应商合作,那么这将更加困难......另外请记住我在 x86 上开发 VxWorks,我们有一个 AMI 为我们的主板定制 BIOS……

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

修改内核以执行此操作的问题是,您必须在 PCI 枚举之前找到可以读取位文件的最佳位置...如果例如磁盘设备驱动程序在 PCI 之后初始化,那么显然您必须做一些对内核进行彻底更改只是为了在 PCI 枚举之前读取位文件,这可能会导致其他烦人的问题......

您可能已经发现了另一个选项,它实际上只适用于开发时间:启动系统,对 fpga 板进行编程,然后进行重置(无需重新启动,例如:sudo reboot now),FPGA 应该保留它的配置,linux应该枚举它......

于 2012-09-14T10:38:03.773 回答
6

打开计算机后,BIOS 会枚举 PCI 总线并尝试满足所有 IO 空间和内存映射 IO (MMIO) 请求。它最初设置这些 BAR,当操作系统加载这些 BAR 时,操作系统可以在它认为合适的情况下更改这些 BAR,同时 PCI 总线驱动程序再次枚举总线。系统的超级用户甚至可以setpci在 BIOS 已经尝试配置它们并且操作系统已经加载之后运行命令来更改这些 BAR(如果操作不当,可能会导致驱动程序失败和其他一些坏事)。

在 BIOS 未为相关卡分配任何资源的情况下,我不得不这样做,因为请求的区域需要 64 位地址,而 BIOS 仅使用 32 位地址分配操作。我能够在事后进行并将这些地址(最初由 BIOS 分配)更改为我认为合适的任何地址,插入内核模块,我的驱动程序将映射并使用这些新分配的地址用于卡,而无需知道区别。

热插拔 PCI-Express 卡存在的问题是,如果没有主板/背板上需要存在的特定热插拔控制器,插槽本身的电源就无法打开/关闭。如果没有这些热插拔控制器来关闭插槽的电源,则在物理插入和/或移除卡(如果仍然存在电源)时,可能会导致微小引脚之间的短路。然而,热插拔事件可以由任一端(主机端点设备)发起。情况似乎并非如此,但是如果您的 FPGA 已经与根复合体建立了链接,则可能的解决方案是生成热插拔中断以导致操作系统中的总线重新扫描。

但是有一个主要问题——如果您的卡实际上没有获得到根联合体的链接,它将无法生成任何热插拔事件;似乎是这样。启动后,FPGA 应该切换 PCIe 总线上的PRESENT线,告诉操作系统有一张卡可以被枚举。一旦检测到,操作系统应该尝试建立到卡的链接并将内存区域分配给设备。在操作系统枚举卡后,您将能够针对它加载驱动程序并在lspci. 您说您使用的是内核 2.6,它确实支持热插拔和动态资源分配,因此只要您的 FPGA 也支持切换 PRESENT PCIe 线的能力,这种方法就应该有效。

于 2014-01-03T21:38:09.530 回答