11. TPH 支持

版权所有:

2024 Advanced Micro Devices, Inc.

作者:

11.1. 概述

TPH(TLP 处理提示)是一项 PCIe 功能,允许端点设备为针对内存空间的请求提供优化提示。 这些提示以称为转向标签 (ST) 的格式嵌入到请求者的 TLP 标头中,使系统硬件(例如根复合体)能够更好地管理这些请求的平台资源。

例如,在具有基于 TPH 的直接数据缓存注入支持的平台上,端点设备可以在其 DMA 流量中包含适当的 ST,以指定数据应写入哪个缓存。 这允许 CPU 内核从缓存中获取数据的概率更高,从而可能提高性能并减少数据处理中的延迟。

11.2. 如何使用 TPH

TPH 在 PCIe 中以可选的扩展功能呈现。 Linux 内核在启动期间处理 TPH 发现,但如果需要使用 TPH,则由设备驱动程序请求启用 TPH。 启用后,驱动程序使用提供的 API 获取目标内存的转向标签,并将 ST 编程到设备的 ST 表中。

11.2.1. 在 Linux 中启用 TPH 支持

为了支持 TPH,内核必须在启用 CONFIG_PCIE_TPH 选项的情况下构建。

11.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);

11.2.3. 管理 ST

转向标签是平台特定的。 PCIe 规范未指定 ST 的来源。 相反,PCI 固件规范定义了一个 ACPI _DSM 方法(请参阅 修订后的缓存局部性 TPH 功能 ECN 的 _DSM),用于检索各种属性的目标内存的 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;
}

11.2.4. 全系统禁用 TPH

有一个内核命令行选项可用于控制 TPH 功能
  • “notph”:将禁用所有端点设备的 TPH。