12. TPH 支援

版權所有:

2024 Advanced Micro Devices, Inc.

作者:

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 將對所有端點裝置停用。