4. PCIe DMA关键概念

在PCIe体系结构中,DMA传输性能并不是由驱动代码单独决定的,而是由事务层、数据链路层、物理层以及设备配置参数共同作用的结果。理解TLP、DLLP、完成包、Max Payload Size、Max Read Request Size、RCB和流量控制机制,是进行DMA性能调优的基础。本节将围绕这些关键概念,建立从协议分层到参数调优的完整认知。

一、核心原理:TLP与DLLP的分工

PCIe协议采用分层结构,其中与DMA性能最直接相关的是事务层和数据链路层。事务层生成TLP(Transaction Layer Packet),它承载真正的读写请求、完成响应和配置访问。一次DMA读操作会发出Mem Read TLP,一次DMA写操作会发出Mem Write TLP,而设备返回的数据则封装在Completion TLP中。

数据链路层则负责可靠传输,它生成DLLP(Data Link Layer Packet)。DLLP不承载用户数据,而是用于ACK/NAK确认、电源管理、流量控制信用更新等。DLLP在链路两端之间传递,对软件不可见,但它直接影响TLP能否顺利发送。如果接收端信用不足,发送端就必须暂停TLP发送,从而影响DMA吞吐。

关键区别:TLP是端到端的事务包,DLLP是链路级的控制包。DMA性能调优主要关注TLP的尺寸、数量和完成机制,同时不能忽视DLLP所维护的流量控制信用。

二、完成包与Split Transaction机制

PCIe读操作采用拆分事务机制。Requester发出读请求TLP后,Completer稍后返回一个或多个Completion TLP。完成包中携带Completion Status、Requester ID、Tag、Byte Count以及数据负载。对于DMA读,设备作为Requester发起读请求,RC或端点作为Completer返回数据。

完成包的管理直接影响读性能。若一次读请求被拆分成过多小完成包,会增加头部开销和中断处理次数;若完成包过大,又可能超过接收端缓冲区能力。因此,Max Payload Size和Max Read Request Size共同决定了读请求和完成包的数据组织方式。

三、Max Payload Size与Max Read Request Size

Max Payload Size(MPS)表示一个TLP中允许携带的最大数据负载,常见值为128B、256B、512B、1024B、2048B、4096B。它由链路两端设备的能力协商决定,实际生效值取双方支持的最小值。

Max Read Request Size(MRRS)表示一个读请求TLP最多可以请求多少数据,常见值同样为128B到4096B。MRRS决定了单次读请求能覆盖的地址范围,也影响完成包的数量和大小。

两者关系可以概括为:MPS限制单个TLP的负载,MRRS限制单个读请求的总量。若MRRS大于MPS,一个读请求会被拆成多个完成包;若MRRS等于MPS,则一个读请求通常对应一个完成包,效率较高。

典型配置示例:
Max Payload Size      = 512B
Max Read Request Size = 512B
一次DMA读请求 512B → 1个Mem Read TLP → 1个Completion TLP(512B数据)
一次DMA读请求 2048B → 1个Mem Read TLP(MRRS=2048B)→ 4个Completion TLP(每个512B)

四、RCB与读完成边界

RCB(Read Completion Boundary)是PCIe规范中定义的一个自然对齐边界,通常为64B或128B。它规定了完成包在地址空间中的拆分边界。当读请求跨越RCB边界时,Completer可能会将完成包拆分成多个,即使MRRS和MPS都足够大。

RCB的存在意味着:即使你把MRRS设置为4096B,如果请求地址跨越了多个RCB边界,完成包仍可能被拆分。因此,在高性能DMA设计中,建议让DMA缓冲区按RCB对齐,并尽量使单次请求落在同一RCB边界内,以减少完成包数量。

调优建议:将DMA描述符中的缓冲区地址按128B或256B对齐,并让传输长度是MPS的整数倍,可以显著减少完成包拆分和TLP头部开销。

五、流量控制与信用机制

PCIe流量控制基于信用(Credit)机制。发送端在发送TLP前,必须确认接收端有足够的信用。信用分为Posted、Non-Posted和Completion三类,每类又分为Header Credit和Data Credit。DLLP负责在链路两端之间更新信用信息。

当DMA大量写入时,Posted Write TLP会消耗Posted Credit;当DMA大量读取时,Non-Posted Read TLP消耗Non-Posted Credit,返回的Completion TLP消耗Completion Credit。如果某一类信用耗尽,发送端必须等待DLLP更新信用后才能继续发送,从而形成背压。

概念所在层次作用调优关注点
TLP事务层承载读写请求与完成数据尺寸、数量、对齐
DLLP数据链路层ACK/NAK、信用更新链路稳定性、信用回收
Completion TLP事务层返回读数据与状态拆分数量、RCB边界
MPS配置参数单TLP最大负载取双方最小值
MRRS配置参数单读请求最大长度与MPS匹配
RCB协议规则完成包拆分边界缓冲区对齐
Flow Control数据链路层防止接收端溢出信用类型与阈值

六、案例场景:DMA读带宽上不去

某平台使用FPGA通过PCIe Gen3 x8向主机内存写入数据,理论带宽约7.8GB/s,但实测DMA读带宽只有3.2GB/s。检查发现:MPS=128B,MRRS=128B,DMA缓冲区未按RCB对齐,且每次读请求只有256B。

调整后:将MPS和MRRS都设置为512B,DMA缓冲区按512B对齐,单次读请求提升到2048B。此时每个读请求产生4个512B完成包,完成包数量减少,TLP头部开销降低,实测带宽提升到6.1GB/s。进一步检查流量控制信用,发现Completion Credit充足,瓶颈主要在请求粒度和完成包拆分。

调整前:
MPS=128B, MRRS=128B, 请求=256B → 2个读请求,多个小完成包
调整后:
MPS=512B, MRRS=2048B, 请求=2048B → 1个读请求,4个512B完成包
带宽:3.2GB/s → 6.1GB/s

七、常见误区与复盘

  • 误区一:MPS越大越好。MPS受限于链路两端设备能力和交换机支持,盲目设置可能导致链路训练失败或降速。
  • 误区二:忽略MRRS与MPS的匹配。MRRS远大于MPS时,完成包会被大量拆分,增加开销。
  • 误区三:不关注RCB对齐。跨RCB边界的请求会被强制拆分,即使参数设置很大也无法避免。
  • 误区四:只看带宽不看信用。流量控制信用不足时,TLP发送会被暂停,表现为带宽波动或下降。
排障顺序建议:先确认链路速率和宽度,再检查MPS/MRRS协商值,然后验证DMA缓冲区对齐和请求粒度,最后观察流量控制信用和DLLP更新是否正常。
PCIe DMA关键概念关系图 Requester(DMA设备) Mem Read / Write TLP MRRS 控制请求长度 MPS 限制 TLP 负载 Completer(RC/端点) Completion TLP RCB 决定拆分边界 Completion Credit PCIe Link TLP 事务包(端到端) DLLP 链路控制(ACK/信用) 流量控制信用 Posted / Non-Posted / Completion Header Credit + Data Credit 参数调优关系 MPS 单TLP最大负载 MRRS 单读请求最大长度 RCB 完成包拆分边界 Flow Control 信用与背压 MPS 与 MRRS 匹配、缓冲区按 RCB 对齐、信用充足 → DMA 吞吐最优

总结来看,TLP和DLLP分别承担事务传输和链路控制,完成包决定读路径效率,MPS和MRRS决定请求与负载粒度,RCB影响完成包拆分,流量控制则保障链路稳定。只有把这些概念放在同一张性能地图中理解,才能在DMA调优时快速定位瓶颈并做出正确配置。