简介

RapidIO 标准是一种基于数据包的结构互连标准,设计用于嵌入式系统。RapidIO 标准的开发由 RapidIO 贸易协会 (RTA) 指导。当前版本的 RapidIO 规范可从 RTA 网站 [1] 公开下载。

本文档介绍了 Linux RapidIO 子系统的基础知识,并提供了有关其主要组件的信息。

1 概述

由于 RapidIO 子系统遵循 Linux 设备模型,因此它通过定义 RapidIO 特定的设备和总线类型并将它们注册到设备模型中,从而集成到内核中,类似于其他总线。

Linux RapidIO 子系统是独立于架构的,因此定义了特定于架构的接口,这些接口为常见的 RapidIO 子系统操作提供支持。

2. 核心组件

典型的 RapidIO 网络是端点和交换机的组合。这些组件中的每一个都由子系统中关联的数据结构表示。RapidIO 子系统的核心逻辑组件在 include/linux/rio.h 文件中定义。

2.1 主端口

主端口 (或 mport) 是一个 RapidIO 接口控制器,它位于执行 Linux 代码的处理器本地。主端口生成和接收 RapidIO 数据包(事务)。在 RapidIO 子系统中,每个主端口都由一个 rio_mport 数据结构表示。此结构包含主端口特定的资源,例如邮箱和门铃。rio_mport 还包括一个唯一的主机设备 ID,当主端口配置为枚举主机时,该 ID 有效。

RapidIO 主端口由子系统特定的 mport 设备驱动程序提供服务,该驱动程序为此子系统定义了功能。为了为 RapidIO 子系统操作提供硬件无关的接口,rio_mport 结构包含 rio_ops 数据结构,其中包含指向 RapidIO 函数的硬件特定实现的指针。

2.2 设备

RapidIO 设备是网络中的任何端点(mport 除外)或交换机。所有设备在 RapidIO 子系统中都由相应的 rio_dev 数据结构表示。设备形成一个全局设备列表和每个网络的设备列表(取决于可用的 mport 和网络的数量)。

2.3 交换机

RapidIO 交换机是一种特殊的设备,它在其端口之间路由数据包,使其到达最终目的地。交换机内的数据包目标端口由内部路由表定义。交换机在 RapidIO 子系统中由 rio_dev 数据结构表示,并由附加的 rio_switch 数据结构扩展,该结构包含交换机特定信息,例如路由表的副本以及指向交换机特定函数的指针。

RapidIO 子系统定义了子系统特定交换机驱动程序的格式和初始化方法,这些驱动程序旨在提供通用交换机管理例程的硬件特定实现。

2.4 网络

RapidIO 网络是互连的端点和交换机设备的组合。系统中已知的每个 RapidIO 网络都由相应的 rio_net 数据结构表示。此结构包括形成同一网络的所有设备和本地主端口的列表。它还包含指向用于与网络中设备通信的默认主端口的指针。

2.5 设备驱动程序

RapidIO 设备特定的驱动程序遵循 Linux 内核驱动程序模型,旨在支持连接到 RapidIO 网络的特定 RapidIO 设备。

2.6 子系统接口

RapidIO 互连规范定义了可用于为所有参与的 RapidIO 设备提供一个或多个通用服务层的功能。这些通用服务可以独立于设备特定的驱动程序运行,也可以由设备特定的驱动程序使用。此类服务提供程序的一个示例是 RIONET 驱动程序,它实现以太网 over RapidIO 接口。由于只能为一个设备注册一个驱动程序,因此所有通用的 RapidIO 服务都必须注册为子系统接口。这允许将多个通用服务附加到同一设备,而不会阻止附加设备特定的驱动程序。

3. 子系统初始化

为了初始化 RapidIO 子系统,平台必须初始化并在 RapidIO 网络中注册至少一个主端口。为了在子系统控制器驱动程序的初始化代码中注册 mport,为每个可用的主端口调用函数 rio_register_mport()。

在所有活动的主端口都注册到 RapidIO 子系统后,可以自动或通过用户空间命令调用枚举和/或发现例程。

RapidIO 子系统可以配置为作为内核的静态链接或模块化组件构建(请参阅下面的详细信息)。

4. 枚举和发现

4.1 概述

RapidIO 子系统配置选项允许用户将枚举和发现方法构建为静态链接组件或可加载模块。枚举/发现方法实现和可用的输入参数定义了任何给定的方法如何附加到可用的 RapidIO mport:简单地附加到所有可用的 mport 或单独附加到指定的 mport 设备。

根据选择的枚举/发现构建配置,有几种方法可以启动枚举和/或发现过程

(a) 静态链接的枚举和发现过程可以使用相应的模块参数在内核初始化期间自动启动。自从引入 RapidIO 子系统以来,这是最初使用的方法。现在,此方法依赖于枚举器模块参数,对于现有的基本枚举/发现方法,该参数为 'rio-scan.scan'。当使用枚举/发现的自动启动时,用户必须确保所有发现端点都在枚举端点之前启动,并且正在等待枚举完成。配置选项 CONFIG_RAPIDIO_DISC_TIMEOUT 定义了发现端点等待枚举完成的时间。如果指定的超时时间到期,则发现过程将终止,而不会获取 RapidIO 网络信息。注意:超时的发现过程可以在稍后使用用户空间命令重新启动,如下所述(如果给定的端点已成功枚举)。

(b) 静态链接的枚举和发现过程可以通过来自用户空间的命令启动。与上面的选项 (a) 相比,此启动方法为系统启动提供了更大的灵活性。在所有参与的端点都已成功启动后,应首先通过发出用户空间命令来启动枚举过程,在枚举完成后,可以在所有剩余的端点上启动发现过程。

(c) 模块化枚举和发现过程可以通过来自用户空间的命令启动。在加载枚举/发现模块后,可以通过发出用户空间命令来启动网络扫描过程。与上面的选项 (b) 类似,必须先启动一个枚举器。

(d) 模块化枚举和发现过程可以通过模块初始化例程启动。在这种情况下,应首先加载枚举模块。

当网络扫描过程启动时,它会根据主端口的配置角色:主机或代理来调用枚举或发现例程。

如果主端口配置为主机端口,则通过分配大于或等于零的主机目标 ID 来执行枚举。可以使用各种方法为主端口分配主机目标 ID,具体取决于 RapidIO 子系统构建配置

(a) 对于静态链接的 RapidIO 子系统核心,请使用命令行参数“rapidio.hdid=”,其中包含按 mport 设备注册顺序的目标 ID 分配列表。例如,在具有两个 RapidIO 控制器的系统中,命令行参数“rapidio.hdid=-1,7”将导致将主机目标 ID=7 分配给第二个 RapidIO 控制器,而将目标 ID=-1 分配给第一个 RapidIO 控制器。

(b) 如果 RapidIO 子系统核心被构建为可加载模块,除了上面显示的方法外,还可以使用在加载期间传递模块参数“hdid=”的传统方法来指定主机目标 ID。

  • 从命令行:“modprobe rapidio hdid=-1,7”,或者

  • 从 modprobe 配置文件中使用配置命令“options”,例如在以下示例中:“options rapidio hdid=-1,7”。modprobe 配置文件的示例在下面的部分中提供。

注意

(i) 如果省略“hdid=”参数,则所有可用的 mport 都将被分配目标 ID = -1;

(ii) 在具有多个 mport 的系统中,“hdid=”参数可以省略列表末尾的目标 ID 分配(默认 = -1)。

如果特定主端口的主机设备 ID 设置为 -1,则将为其执行发现过程。

枚举和发现例程使用 RapidIO 维护事务来访问设备的配置空间。

注意:如果 RapidIO 交换机特定的设备驱动程序被构建为可加载模块,则必须在枚举/发现过程开始之前加载它们。造成此要求的原因是枚举/发现方法在早期阶段调用特定于供应商的回调。

4.2 自动启动枚举和发现

自动枚举/发现启动方法仅适用于内置的枚举/发现 RapidIO 配置选择。要通过现有的基本枚举器方法启用自动枚举/发现启动,请使用引导命令行参数 “rio-scan.scan=1”。

此配置要求同步启动形成网络的 所有 RapidIO 端点,以便进行枚举/发现。发现端点必须在枚举开始之前启动,以确保所有 RapidIO 控制器都已初始化并准备好被发现。配置参数 CONFIG_RAPIDIO_DISC_TIMEOUT 定义了发现端点等待枚举完成的时间(以秒为单位)。

当选择自动枚举/发现启动时,基本方法的初始化例程会调用 rio_init_mports() 来对所有已知的 mport 设备执行枚举或发现。

根据 RapidIO 网络的大小和配置,由于需要同步启动所有端点,这种自动枚举/发现启动方法可能难以使用。

4.3 用户空间启动枚举和发现

用户空间启动枚举和发现可以与内置和模块化构建配置一起使用。对于用户空间控制的启动,RapidIO 子系统会创建 sysfs 只写属性文件 “/sys/bus/rapidio/scan”。要对特定的 mport 设备启动枚举或发现过程,用户需要将 mport_ID(不是 RapidIO 目标 ID)写入该文件。mport_ID 是在 mport 设备注册期间分配的顺序号(0 ... RIO_MAX_MPORTS)。例如,对于具有单个 RapidIO 控制器的机器,该控制器的 mport_ID 始终为 0。

要对所有可用的 mport 启动 RapidIO 枚举/发现,用户可以将 “-1”(或 RIO_MPORT_ANY)写入扫描属性文件。

4.4 基本枚举方法

这是 RapidIO 子系统代码首次发布以来可用的原始枚举/发现方法。枚举过程是按照 RapidIO 互连规范:附录 I [1] 中概述的枚举算法实现的。

此方法可以配置为静态链接或可加载模块。该方法的单个参数 “scan” 允许从模块初始化例程触发枚举/发现过程。

此枚举/发现方法只能启动一次,如果它是作为模块构建的,则不支持卸载。

枚举过程使用递归的深度优先算法遍历网络。当发现新设备时,枚举器通过写入主机设备 ID 锁 CSR 来获得该设备的所有权。这样做是为了确保枚举器具有枚举设备的专有权。如果成功获取设备所有权,枚举器将分配一个新的 rio_dev 结构并根据设备功能对其进行初始化。

如果该设备是端点,则会为其分配唯一的设备 ID,并且其值将写入设备的基设备 ID CSR。

如果该设备是交换机,则枚举器会分配一个额外的 rio_switch 结构来存储特定于交换机的信息。然后,针对已知的 RapidIO 交换机表查询交换机的供应商 ID 和设备 ID。每个交换机表条目都包含一个指向特定于交换机的初始化例程的指针,该例程初始化指向其余特定于交换机的操作的指针,并在必要时执行硬件初始化。RapidIO 交换机没有唯一的设备 ID;如果需要访问其配置寄存器,它依赖于跳计数和路由来实现附加端点的设备 ID。如果交换机(或交换机链)没有任何附加端点(枚举器除外),则将分配一个伪设备 ID 以配置到该交换机的路由。在没有端点的交换机链的情况下,使用一个伪设备 ID 来配置通过整个链的路由,并且通过它们的跳计数来区分交换机。

对于端点和交换机,枚举器都会将唯一的组件标签写入设备的组件标签 CSR 中。该唯一值由错误管理通知机制用于识别正在报告错误管理事件的设备。

通过迭代该交换机的每个活动出口端口来完成交换机之外的枚举。对于每个活动链路,会将到默认设备 ID(8 位系统为 0xFF,16 位系统为 0xFFFF)的路由临时写入路由表。该算法通过使用 hopcount + 1 和默认设备 ID 调用自身来递归,以便访问活动端口上的设备。

在主机完成整个网络的枚举后,它通过清除设备 ID 锁(调用 rio_clear_locks())来释放设备。对于系统中的每个端点,它会在端口通用控制 CSR 中设置已发现位,以指示枚举已完成,并且允许代理执行网络的被动发现。

发现过程由代理执行,类似于上述描述的枚举过程。但是,发现过程是在不更改现有路由的情况下执行的,因为代理只收集有关 RapidIO 网络结构的信息并建立已发现设备的内部映射。这样,RapidIO 子系统的每个基于 Linux 的组件都有一个完整的网络视图。发现过程可以由多个代理同时执行。在初始化其 RapidIO 主端口后,每个代理会等待主机完成枚举,等待时间为配置的等待时间段。如果此等待时间段在枚举完成之前到期,则代理会跳过 RapidIO 发现并继续进行剩余的内核初始化。

4.5 添加新的枚举/发现方法

RapidIO 子系统代码组织允许添加新的枚举/发现方法作为新的配置选项,而不会对核心 RapidIO 代码产生重大影响。

必须将新的枚举/发现方法附加到一个或多个 mport 设备,然后才能启动枚举/发现过程。通常,方法的模块初始化例程会调用 rio_register_scan() 将枚举器附加到指定的 mport 设备(或多个设备)。基本枚举器实现演示了此过程。

4.6 使用可加载的 RapidIO 交换机驱动程序

如果 RapidIO 交换机驱动程序构建为可加载模块,则用户必须确保在枚举/发现开始之前加载它们。可以通过在特定于 RapidIO 的 modprobe 配置文件中指定前置或后置依赖项来自动化此过程,如下例所示。

文件 /etc/modprobe.d/rapidio.conf

# Configure RapidIO subsystem modules

# Set enumerator host destination ID (overrides kernel command line option)
options rapidio hdid=-1,2

# Load RapidIO switch drivers immediately after rapidio core module was loaded
softdep rapidio post: idt_gen2 idtcps tsi57x

# OR :

# Load RapidIO switch drivers just before rio-scan enumerator module is loaded
softdep rio-scan pre: idt_gen2 idtcps tsi57x

--------------------------
注意

在上面的示例中,必须删除或注释掉其中一个 “softdep” 命令,以保持所需的模块加载顺序。

5. 参考资料

[1] RapidIO 贸易协会。 RapidIO 互连规范。

http://www.rapidio.org.

[2] Rapidio TA。技术比较。

http://www.rapidio.org/education/technology_comparisons/

[3] RapidIO 对 Linux 的支持。

https://lwn.net/Articles/139118/

[4] Matt Porter。适用于 Linux 的 RapidIO。渥太华 Linux 研讨会,2005

https://linuxkernel.org.cn/doc/ols/2005/ols2005v2-pages-43-56.pdf