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 控制器交互,该转换器将低速或全速事务转换为高速“分割事务”,不会浪费传输带宽。

在撰写本文时,该驱动程序已被发现在以下公司 (按字母顺序排列) 的 EHCI 实现中工作:英特尔、NEC、飞利浦和 VIA。其他供应商也正在推出其他 EHCI 实现;您应该期望此驱动程序也能与它们一起工作。

虽然 USB 存储设备自 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。(使用执行磁盘 I/O 的 usb-storage 查看;观察请求队列!)

“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 MB/秒的传输速率,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% 的周期性带宽分配。对此进行描述。