Based on kernel version 7.2. Page generated on 2026-08-20 08:41 EST.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/usb/ehci.rst
:翻译:
白钶凡 Kefan Bai <baikefan@leap-io-kernel.com>
:校译:
=========
EHCI 驱动
=========
2002年12月27日
EHCI 驱动用于通过支持 USB 2.0 的主机控制器
硬件与高速 USB 2.0 设备通信。USB 2.0 兼容
USB 1.1 标准,它定义了三种传输速率:
- “高速”(High Speed)480 Mbit/sec(60 MByte/sec)
- “全速”(Full Speed)12 Mbit/sec(1.5 MByte/sec)
- “低速”(Low Speed)1.5 Mbit/sec
USB 1.1 仅支持全速与低速。
高速设备可以在 USB 1.1 系统上使用,
但速度会降到 USB 1.1 的速率。
USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们
插入 EHCI 控制器时,会被交由 USB 1.1 的伴随
(companion)控制器处理,该控制器通常是 OHCI 或 UHCI。
当 USB 1.1 设备插入 USB 2.0 集线器时,它们通过
集线器中的事务转换器(Transaction Translator,TT)
与 EHCI 控制器交互,该转换器将低速或全速事务转换为
高速分割事务,从而避免浪费传输带宽。
截至本文撰写时,该驱动已在以下 EHCI 实现上成功运行
(按字母顺序):Intel、NEC、Philips 和 VIA。
其他供应商的 EHCI 实现正在陆续问世;
预计该驱动在这些实现上也可正常运行。
自 2001 年年中起,usb-storage 设备就已可用
(在 2.4 版该驱动上速度相当不错),
集线器则直到 2001 年底才开始可用,而其他类型的高速设备
似乎要等到更多系统内置 USB 2.0 后才会出现。
这类新系统从 2002 年初开始上市,
并在 2002 年下半年变得更加常见。
注意,USB 2.0 支持并不只是 EHCI 本身。
它还需要对 Linux-USB 核心 API 作出其他修改,
包括 hub 驱动;不过这些修改并不需要真正改变
暴露给 USB 设备驱动的基本 ``usbcore`` API。
- David Brownell
<dbrownell@users.sourceforge.net>
功能
====
该驱动会定期在 x86 硬件上进行测试,
也已在 PPC 硬件上使用,因此大小端问题应当已经解决。
因此可以认为,它已经处理好了所有必要的 PCI 细节,
所以即便在 DMA 映射有些特殊的系统上,
I/O 也应能正常运行。
传输类型
--------
截至本文撰写时,该驱动应当已经能够很好地处理
所有控制传输、批量传输和中断传输,
包括通过 USB 2.0 集线器中的事务转换器
与 USB 1.1 设备通信;但仍可能存在 bug。
高速等时(ISO)传输支持也已可用,但截至本文撰写时,
还没有 Linux 驱动使用这项支持。
目前尚不支持通过事务转换器实现全速等时传输。
需要注意,ISO 传输的 split transaction 支持
与高速 ISO 传输几乎无法共用代码,
因为 EHCI 用不同的数据结构表示它们。
因此,目前大多数 USB 音频和视频设备
还不能通过高速总线连接使用。
驱动行为
--------
所有类型的传输都可以排队。
这意味着来自一个接口驱动的控制传输
(或通过 usbfs 发出的控制传输)不会干扰
另一个驱动的控制传输,而且中断传输可以使用 1 帧的周期,
而不必担心中断处理开销导致的数据丢失。
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/sec 的“原始传输率”对所有设备都成立,
但总吞吐量还会受到诸如单个高速包之间的延迟、
驱动是否足够聪明,以及系统整体负载等因素的影响。
延迟也是性能考量因素。
批量传输最常用于关注吞吐量的场景。
需要记住的是,批量传输总是以 512 字节包为单位,
而一个 USB 2.0 微帧中最多只能容纳 13 个这样的包。
8 个 USB 2.0 微帧构成一个 USB 1.1 帧;
一个微帧的时长是 1 毫秒 / 8 = 125 微秒。
因此,只要硬件和设备驱动软件都允许,
批量传输可提供超过 50 MByte/sec 的带宽。
周期性传输模式(等时和中断)允许使用更大的包大小,
从而可以逼近所宣称的 480 Mbit/sec 传输率。
硬件性能
--------
截至本文撰写时,单个 USB 2.0 设备的最大传输速率
通常约为 20 MByte/sec。
这当然会随着时间改变:一些设备现在更快,一些更慢。
第一代 NEC EHCI 实现似乎存在
大约 28 MByte/sec 的硬件瓶颈。
虽然这对单个 20 MByte/sec 的设备显然已经够用,
但把三个这样的设备挂到同一总线上,
并不能得到 60 MByte/sec。
问题似乎在于控制器硬件无法并发进行 USB 与 PCI 访问,
因此它每个微帧只会尝试 6 次(也许是 7 次)
USB 事务,而不是 13 次。
(对一个比其他产品早上市一年的芯片来说,
这是个合理的妥协!)
预计较新的实现会在这方面做得更好,
通过投入更多芯片面积来解决这个问题,
使新的主板芯片组更接近 60 MByte/sec 的目标。
这既包括 NEC 的更新实现,也包括其他厂商的芯片。
主机从 EHCI 控制器收到“请求已完成”中断的最小延迟
为一个微帧(125 微秒)。该延迟可以调节;
驱动提供了一个模块选项。默认情况下,
``ehci-hcd`` 使用最小延迟,这意味着当发出一个控制
或批量请求时,通常可以在不到 250 微秒内得知它已完成
(具体取决于传输大小)。
软件性能
--------
即便只是要达到 20 MByte/sec 的传输速率,
Linux-USB 设备驱动也必须让 EHCI 队列始终保持满载。
这意味着要发出较大的请求,
或者在需要发出一连串小请求时使用批量请求排队。
如果驱动未做到这一点,那么会直接从性能结果上表现出来。
在典型情况下,使用 ``usb_bulk_msg()``
以 4 KB 块循环写出,
会浪费超过一半的 USB 2.0 带宽。
I/O 完成与驱动发出下一次请求之间的延迟,
通常会比一次 I/O 本身耗时更长。
如果同样的循环改用 16 KB 块,会好一些;
若使用一连串 128 KB 块,则浪费会少得多。
但与其依赖这么大的 I/O 缓冲区来让同步 I/O 高效,
不如直接向主机控制器排入多个(批量)请求,
然后等待它们全部完成(或在出错时取消)。
这种 URB 排队方式对所有 USB 1.1
主机控制器驱动也同样适用。
在 Linux 2.5 内核中,定义了新的 ``usb_sg_*()`` API;
它们会把 scatterlist 中的所有缓冲区都排入队列。
它们还使用 scatterlist 的 DMA 映射
(其中可能应用 IOMMU)并减少中断次数,
这些都有助于让高速传输尽可能快地运行。
待办:
中断传输和等时(ISO)传输的性能问题。
这些周期性传输都是完全调度的,因此,主要问题可能在于如何触发高带宽模式。
待办:
通过 ``sysfs`` 中的 ``uframe_periodic_max`` 参数,
可以分配超过标准 80% 的周期性带宽。
后续将对此进行说明。
|