EHCI 驱动程序

2002 年 12 月 27 日

EHCI 驱动程序用于通过 USB 2.0 功能的主机控制器硬件与高速 USB 2.0 设备通信。 USB 2.0 标准与 USB 1.1 标准兼容。 它定义了三个传输速度

  • “高速” 480 Mbit/秒 (60 MByte/秒)

  • “全速” 12 Mbit/秒 (1.5 MByte/秒)

  • “低速” 1.5 Mbit/秒

USB 1.1 仅处理全速和低速。 高速设备可以在 USB 1.1 系统上使用,但它们会降低到 USB 1.1 速度。

USB 1.1 设备也可以在 USB 2.0 系统上使用。 当插入 EHCI 控制器时,它们会被交给 USB 1.1 “伴侣”控制器,该控制器是通常与此类设备一起使用的 OHCI 或 UHCI 控制器。 当 USB 1.1 设备插入 USB 2.0 集线器时,它们通过集线器中的“事务转换器”(TT) 与 EHCI 控制器交互,该转换器将低速或全速事务转换为高速“拆分事务”,不会浪费传输带宽。

在撰写本文时,已发现该驱动程序可与(按字母顺序排列)Intel、NEC、Philips 和 VIA 的 EHCI 实现一起使用。 其他供应商也开始提供其他 EHCI 实现; 您应该期望此驱动程序也能与它们一起使用。

虽然 usb-storage 设备自 2001 年年中开始可用(在此驱动程序的 2.4 版本上运行速度很快),但集线器自 2001 年底才可用,并且其他类型的高速设备似乎处于暂停状态,直到更多系统内置 USB 2.0。 自 2002 年初以来,此类新系统已经上市,并在 2002 年下半年变得更加普遍。

请注意,USB 2.0 支持不仅仅涉及 EHCI。 它需要对 Linux-USB 核心 API 进行其他更改,包括集线器驱动程序,但这些更改无需真正更改暴露给 USB 设备驱动程序的基本“usbcore” API。

功能

该驱动程序在 x86 硬件上定期进行测试,并且也已在 PPC 硬件上使用,因此大小端问题应该已经消失。 据信它可以完成所有正确的 PCI 魔术,因此即使在具有有趣 DMA 映射问题的系统上,I/O 也能正常工作。

传输类型

在撰写本文时,该驱动程序应该可以轻松处理所有控制、批量和中断传输,包括通过 USB 2.0 集线器中的事务转换器 (TT) 向 USB 1.1 设备发出的请求。 但您可能会发现错误。

高速同步 (ISO) 传输支持也已启用,但在撰写本文时,没有 Linux 驱动程序使用该支持。

通过事务转换器的全速同步传输支持尚不可用。 请注意,ISO 传输的拆分事务支持无法与高速 ISO 传输的代码共享太多代码,因为 EHCI 使用不同的数据结构来表示这些传输。 因此,目前,大多数 USB 音频和视频设备无法连接到高速总线。

驱动程序行为

所有类型的传输都可以排队。 这意味着来自一个接口上的驱动程序(或通过 usbfs)的控制传输不会干扰来自另一个驱动程序的传输,并且中断传输可以使用一帧的时间间隔,而不会因中断处理成本而导致数据丢失。

EHCI 根集线器代码将 USB 1.1 设备交给其伴侣控制器。 此驱动程序无需了解有关这些驱动程序的任何信息; 已经可以工作的 OHCI 或 UHCI 驱动程序无需因 EHCI 驱动程序也存在而进行更改。

电源管理存在一些问题; 目前暂停/恢复行为不太正确。

此外,在安排定期事务(中断和同步传输)时,也采取了一些捷径。 这些对可以安排的定期事务的数量施加了一些限制,并阻止使用小于一帧的轮询间隔。

使用

假设您有一个 EHCI 控制器(在 PCI 卡或主板上)并将此驱动程序编译为模块,请像这样加载它

# modprobe ehci-hcd

并通过以下方式删除它

# rmmod ehci-hcd

您还应该有一个“伴侣控制器”的驱动程序,例如“ohci-hcd”或“uhci-hcd”。 如果 EHCI 驱动程序出现任何问题,请删除其模块,然后该伴侣控制器的驱动程序将接管(以较低速度)先前由 EHCI 驱动程序处理的所有设备。

模块参数(传递给“modprobe”)包括

log2_irq_thresh (默认 0)

默认中断延迟的 Log2,以微帧为单位。 默认值为 0,表示 1 个微帧(125 微秒)。 最大值为 6,表示 2^6 = 64 个微帧。 这控制 EHCI 控制器发出中断的频率。

如果您在 2.5 内核上使用此驱动程序,并且启用了 USB 调试支持,您将在任何 EHCI 控制器的“sysfs”目录中看到三个文件

“async”

转储用于控制和批量传输的异步计划。 显示每个活动的 qh 和等待的 qtd,通常每个 urb 一个 qtd。 (使用 usb-storage 进行磁盘 I/O 来查看它;观察请求队列!)

“periodic”

转储用于中断和同步传输的定期计划。 不显示 qtd。

“registers”

显示控制器寄存器状态,以及

这些文件的内容可以帮助识别驱动程序问题。

设备驱动程序不应关心它们是否在 EHCI 上运行,但它们可能需要检查“usb_device->speed == USB_SPEED_HIGH”。 高速设备可以执行全速(或低速)设备无法执行的操作,例如“高带宽”定期(中断或 ISO)传输。 此外,当以高速运行时,设备描述符中的某些值(例如定期传输的轮询间隔)使用不同的编码。

但是,请务必通过 USB 2.0 集线器测试设备驱动程序。 当使用事务转换器时,这些集线器以不同的方式报告某些故障,例如断开连接; 已观察到一些驱动程序在看到与 OHCI 或 UHCI 报告的不同故障时表现不佳。

性能

USB 2.0 吞吐量受两个主要因素限制:主机控制器处理请求的速度以及设备响应请求的速度。 所有设备都遵守 480 Mbit/秒的“原始传输速率”,但总吞吐量也受到各个高速数据包之间的延迟、驱动程序智能以及当然的整体系统负载等问题的影响。 延迟也是一个性能问题。

批量传输最常用于吞吐量是一个问题的情况。 重要的是要记住,批量传输始终采用 512 字节的数据包,并且最多有 13 个数据包适合一个 USB 2.0 微帧。 八个 USB 2.0 微帧适合一个 USB 1.1 帧; 一个微帧是 1 毫秒/8 = 125 微秒。

因此,当硬件和设备驱动程序软件允许时,批量传输的可用带宽超过 50 MByte/秒。 定期传输模式(同步和中断)允许更大的数据包大小,从而使您接近引用的 480 MBit/秒传输速率。

硬件性能

在撰写本文时,单个 USB 2.0 设备往往在 20 MByte/秒左右的传输速率达到最大值。 当然,这可能会发生变化; 并且一些设备现在更快,而另一些设备则更慢。

第一个 NEC EHCI 实现似乎在 28 MByte/秒左右的总传输速率处存在硬件瓶颈。 虽然这对于 20 MByte/秒的单个设备来说显然足够,但将三个这样的设备放到一个总线上并不能获得 60 MByte/秒。 问题似乎在于控制器硬件不会同时进行 USB 和 PCI 访问,因此它每个微帧仅尝试六个(或可能七个)USB 事务,而不是十三个。 (对于一个比其他所有产品早一年上市的产品来说,这似乎是一个合理的折衷方案!)

预计较新的实现会更好地解决这个问题,投入更多的硅片空间来解决该问题,以便新的主板芯片组能够更接近 60 MByte/秒的目标。 这包括 NEC 的更新实现,以及其他供应商的硅片。

主机从 EHCI 控制器接收中断以指示请求完成的最小延迟为一个微帧(125 微秒)。 该延迟是可调的; 有一个模块选项。 默认情况下,ehci-hcd 驱动程序使用最小延迟,这意味着如果您发出控制或批量请求,您通常可以期望在不到 250 微秒内得知它已完成(具体取决于传输大小)。

软件性能

为了获得高达 20 MByte/秒的传输速率,Linux-USB 设备驱动程序需要保持 EHCI 队列满。 这意味着发出大请求,或者如果需要发出 一系列小请求,则使用批量排队。 当驱动程序不这样做时,它们的性能结果将会显示出来。

在典型情况下,usb_bulk_msg() 循环写入 4 KB 的块将浪费超过一半的 USB 2.0 带宽。 I/O 完成与驱动程序发出下一个请求之间的延迟将比 I/O 更长。 如果同一个循环使用 16 KB 的块,情况会更好; 一系列 128 KB 的块会浪费更少。

但是,与其依赖如此大的 I/O 缓冲区来使同步 I/O 效率更高,不如直接将多个(批量)请求排队到 HC,然后等待它们全部完成(或因错误而被取消)。 这种 URB 排队也应该适用于所有 USB 1.1 HC 驱动程序。

在 Linux 2.5 内核中,定义了新的 usb_sg_*() api 调用; 它们对来自散布列表的所有缓冲区进行排队。 它们还使用散布列表 DMA 映射(这可能会应用 IOMMU)和 IRQ 减少,所有这些都将有助于使高速传输尽可能快地运行。

待定

中断和 ISO 传输性能问题。 这些定期传输已完全安排,因此主要问题可能是如何触发“高带宽”模式。

待定

可以通过 sysfs uframe_periodic_max 参数实现超过标准 80% 定期带宽分配的分配。 描述一下。