12. TPH 支持¶
- 版权所有:
2024 Advanced Micro Devices, Inc.
- 作者:
Eric van Tassell <eric.vantassell@amd.com>
Wei Huang <wei.huang2@amd.com>
12.1. 概述¶
TPH (TLP 处理提示) 是一种 PCIe 功能,它允许端点设备为面向内存空间的请求提供优化提示。这些提示以转向标签 (Steering Tags, STs) 的格式嵌入在请求者的 TLP 报头中,使系统硬件(例如根联合体)能够更好地管理这些请求的平台资源。
例如,在支持基于 TPH 的直接数据缓存注入的平台上,端点设备可以在其 DMA 流量中包含适当的 ST,以指定数据应写入哪个缓存。这使得 CPU 核心从缓存中获取数据的可能性更高,从而可能提高性能并减少数据处理中的延迟。
12.2. 如何使用 TPH¶
TPH 在 PCIe 中作为可选的扩展功能呈现。Linux 内核在启动期间处理 TPH 的发现,但如果需要利用 TPH,则由设备驱动程序请求启用 TPH。一旦启用,驱动程序使用提供的 API 获取目标内存的转向标签,并将 ST 编程到设备的 ST 表中。
12.2.1. 在 Linux 中启用 TPH 支持¶
要支持 TPH,内核必须在启用 CONFIG_PCIE_TPH 选项的情况下构建。
12.2.2. 管理 TPH¶
要为设备启用 TPH,请使用以下函数
int pcie_enable_tph(struct pci_dev *pdev, int mode);
此函数为具有特定 ST 模式的设备启用 TPH 支持。当前支持的模式包括
PCI_TPH_ST_NS_MODE - 无 ST 模式
PCI_TPH_ST_IV_MODE - 中断向量模式
PCI_TPH_ST_DS_MODE - 设备特定模式
pcie_enable_tph()
在启用前会检查所请求的模式是否实际受设备支持。设备驱动程序可以根据 pcie_enable_tph()
的返回值判断支持哪种 TPH 模式并正确启用。
要禁用 TPH,请使用以下函数
void pcie_disable_tph(struct pci_dev *pdev);
12.2.3. 管理 ST¶
转向标签是平台特定的。PCIe 规范没有明确指定 ST 的来源。相反,PCI 固件规范定义了一个 ACPI _DSM 方法(参见 《针对缓存局部性 TPH 功能修订的 _DSM ECN》),用于检索具有各种属性的目标内存的 ST。此实现支持的就是这种方法。
要检索与特定 CPU 关联的目标内存的转向标签,请使用以下函数
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
unsigned int cpu_uid, u16 *tag);
参数 type 用于指定目标内存的类型,即易失性或持久性。参数 cpu_uid 指定内存关联的 CPU。
检索到 ST 值后,设备驱动程序可以使用以下函数将 ST 写入设备
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
u16 tag);
参数 index 是要写入 ST 标签的 ST 表条目索引。pcie_tph_set_st_entry()
将确定 ST 表的正确位置(无论是在 MSI-X 表中还是在 TPH 扩展功能空间中),并将转向标签写入 index 参数指向的 ST 条目。
如何使用这些 TPH 函数完全由驱动程序决定。例如,当 RX/TX 队列的中断亲和性发生变化时,网络设备驱动程序可以使用上述 TPH API 更新转向标签。这是一个 IRQ 亲和性通知器的示例代码
static void irq_affinity_notified(struct irq_affinity_notify *notify,
const cpumask_t *mask)
{
struct drv_irq *irq;
unsigned int cpu_id;
u16 tag;
irq = container_of(notify, struct drv_irq, affinity_notify);
cpumask_copy(irq->cpu_mask, mask);
/* Pick a right CPU as the target - here is just an example */
cpu_id = cpumask_first(irq->cpu_mask);
if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
&tag))
return;
if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
return;
}
12.2.4. 系统范围禁用 TPH¶
- 有一个内核命令行选项可用于控制 TPH 功能
“notph”:TPH 将对所有端点设备禁用。