2、UFS基础:UFS协议概述、DMA在UFS中的角色、传输性能关键指标

要优化 UFS 的 DMA 传输性能,第一步不是调参数,而是把“数据到底怎么从主机内存走到闪存、又怎么回来”这条链路看清楚。UFS(Universal Flash Storage)并不是一条简单的并行总线,而是一套带命令队列、分层协议和双向差分链路的高速存储子系统。DMA 在其中扮演的是“搬运执行者”,而真正决定性能上限的,是协议层、链路层与设备内部处理能力的共同结果。

一、UFS 协议概述:三层结构与双通道链路

UFS 的协议栈可以概括为三层:应用层(UFS Command Set,如 SCSI 命令集)、传输协议层(UTP,UniPro Transport Protocol)和互连层(UIC,UniPro Interconnect)。主机侧由 UFS Host Controller(通常符合 UFSHCI 规范)驱动,设备侧是 UFS 设备(含 NAND 与控制器)。两者之间通过 M-PHY 差分链路连接,典型配置为两条 Lane,每条 Lane 可独立收发,形成全双工通信。

命令与数据是分离的:主机通过 UTP 提交 UPIU(UFS Protocol Information Unit),其中包含命令 UPIU、数据 UPIU、响应 UPIU 等类型。数据阶段由 DMA 负责把主机内存中的 scatter-gather 缓冲区与设备侧的数据请求对应起来。理解这一点很关键:UFS 的性能瓶颈往往不在“命令下发”,而在数据搬运与设备内部调度。

UFS 协议栈与 DMA 数据通路 主机侧 Host 应用 / 文件系统 UFS 驱动 / SCSI 命令 UFSHCI 主机控制器 DMA 引擎 / 描述符 UniPro / M-PHY 链路 Lane 0 / Lane 1 全双工 UPIU 命令 / 数据 / 响应 UFS 设备 Device UniPro 端点 UFS 设备控制器 命令队列 / 调度器 NAND 阵列

二、DMA 在 UFS 中的角色:从描述符到数据搬运

在 UFS 中,DMA 不是“可选加速”,而是数据通路的必要组成。主机侧 UFSHCI 通过 UTRD(UTP Transfer Request Descriptor)描述一次传输:命令 UPIU 放在哪里、数据缓冲区在哪里、响应写回哪里。DMA 引擎读取这些描述符后,按 scatter-gather 列表把数据从主机内存搬到设备侧,或从设备侧搬回主机内存。

关键点有三个:

  • 命令与数据解耦:命令 UPIU 很小,数据 UPIU 可能很大,DMA 主要承担大数据块的搬运。
  • 描述符链决定效率:如果缓冲区碎片化严重,DMA 需要处理大量小描述符,开销上升。
  • 队列深度影响并发:UFS 支持多命令队列,DMA 可以在多个请求之间交错搬运,但受限于链路与设备内部调度。

一句话理解:CPU 负责“下命令”,DMA 负责“搬数据”,UFS 链路负责“运数据”,NAND 负责“存数据”。优化 DMA 传输性能,本质是让这四者节奏匹配。

三、传输性能关键指标:看什么、怎么算

评估 UFS DMA 传输性能时,不能只看一个“顺序读速度”。常用指标包括:

指标 含义 典型关注点
顺序读写带宽 大块连续数据传输速率 链路利用率、DMA 大块搬运效率
随机 IOPS 单位时间完成的随机小 IO 次数 命令队列深度、设备调度、DMA 描述符开销
访问延迟 从命令下发到数据返回的时间 命令处理、链路往返、NAND 读取时间
队列深度 同时未完成的命令数量 并发能力、DMA 通道利用率
CPU 占用率 主机 CPU 参与数据传输的比例 DMA 是否真正卸载了数据搬运

这些指标之间存在制约关系。例如,提高队列深度可以提升 IOPS,但如果 DMA 描述符过于碎片化,延迟反而会上升;顺序带宽很高,不代表随机小 IO 性能好。因此,优化前必须明确目标场景:是追求大文件吞吐,还是低延迟随机访问。

四、案例与场景:一次 4KB 随机读的完整路径

假设主机发起一次 4KB 随机读,路径大致如下:

  1. 应用层发起读请求,文件系统转换为 SCSI READ 命令。
  2. UFS 驱动构造命令 UPIU,并准备数据缓冲区描述符。
  3. UFSHCI 将 UTRD 写入主机内存,通知 DMA 引擎。
  4. DMA 读取描述符,通过 UniPro 链路发送命令 UPIU。
  5. 设备控制器解析命令,从 NAND 读取数据到设备缓冲区。
  6. 设备通过数据 UPIU 返回数据,DMA 将其搬入主机内存。
  7. 响应 UPIU 返回,驱动完成回调,通知应用。

在这个路径中,DMA 的耗时主要出现在第 4 步和第 6 步。如果数据缓冲区在物理内存中不连续,DMA 需要多次访问描述符,链路层也可能被拆分成多个小包,导致有效带宽下降。

实操提示:在 Linux 下可以通过 cat /sys/kernel/debug/ufs/... 或厂商工具查看 UFS 链路状态、命令队列深度和错误计数。优化前先确认 DMA 是否成为瓶颈,而不是盲目调整链路速率。

五、常见误区与复盘

  • 误区一:只看峰值带宽。峰值带宽通常是大块顺序读写的理想值,实际随机场景可能只有其十分之一。
  • 误区二:认为 DMA 一定比 CPU 快。DMA 的优势是卸载 CPU,但如果描述符管理不当,DMA 自身也会成为瓶颈。
  • 误区三:忽略设备内部调度。UFS 设备内部的命令队列和 NAND 调度对性能影响很大,主机侧优化无法完全弥补。
  • 误区四:不区分读写路径。写操作涉及缓存刷新和垃圾回收,延迟通常高于读操作,优化策略也不同。
# 示例:查看 UFS 设备基本信息与链路状态
cat /sys/class/scsi_host/host0/device/ufs_device/health
cat /sys/kernel/debug/ufs/host0/link_status
# 关注字段:lane_count, gear, pwm_mode, hibern8_state

复盘时建议按“命令下发 → DMA 搬运 → 链路传输 → 设备处理 → 数据返回”五段拆解耗时,定位真正的瓶颈段。只有把协议结构、DMA 角色和性能指标三者对应起来,后续的优化手段才有明确的发力点。