mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
48d0fd2b90
Add a document for the TPH feature, including description of "notph" kernel parameter and the API interface. Co-developed-by: Eric Van Tassell <Eric.VanTassell@amd.com> Link: https://lore.kernel.org/r/20241002165954.128085-4-wei.huang2@amd.com Signed-off-by: Eric Van Tassell <Eric.VanTassell@amd.com> Signed-off-by: Wei Huang <wei.huang2@amd.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com> Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com> Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
133 lines
4.6 KiB
ReStructuredText
133 lines
4.6 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
===========
|
|
TPH Support
|
|
===========
|
|
|
|
:Copyright: 2024 Advanced Micro Devices, Inc.
|
|
:Authors: - Eric van Tassell <eric.vantassell@amd.com>
|
|
- Wei Huang <wei.huang2@amd.com>
|
|
|
|
|
|
Overview
|
|
========
|
|
|
|
TPH (TLP Processing Hints) is a PCIe feature that allows endpoint devices
|
|
to provide optimization hints for requests that target memory space.
|
|
These hints, in a format called Steering Tags (STs), are embedded in the
|
|
requester's TLP headers, enabling the system hardware, such as the Root
|
|
Complex, to better manage platform resources for these requests.
|
|
|
|
For example, on platforms with TPH-based direct data cache injection
|
|
support, an endpoint device can include appropriate STs in its DMA
|
|
traffic to specify which cache the data should be written to. This allows
|
|
the CPU core to have a higher probability of getting data from cache,
|
|
potentially improving performance and reducing latency in data
|
|
processing.
|
|
|
|
|
|
How to Use TPH
|
|
==============
|
|
|
|
TPH is presented as an optional extended capability in PCIe. The Linux
|
|
kernel handles TPH discovery during boot, but it is up to the device
|
|
driver to request TPH enablement if it is to be utilized. Once enabled,
|
|
the driver uses the provided API to obtain the Steering Tag for the
|
|
target memory and to program the ST into the device's ST table.
|
|
|
|
Enable TPH support in Linux
|
|
---------------------------
|
|
|
|
To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
|
|
enabled.
|
|
|
|
Manage TPH
|
|
----------
|
|
|
|
To enable TPH for a device, use the following function::
|
|
|
|
int pcie_enable_tph(struct pci_dev *pdev, int mode);
|
|
|
|
This function enables TPH support for device with a specific ST mode.
|
|
Current supported modes include:
|
|
|
|
* PCI_TPH_ST_NS_MODE - NO ST Mode
|
|
* PCI_TPH_ST_IV_MODE - Interrupt Vector Mode
|
|
* PCI_TPH_ST_DS_MODE - Device Specific Mode
|
|
|
|
`pcie_enable_tph()` checks whether the requested mode is actually
|
|
supported by the device before enabling. The device driver can figure out
|
|
which TPH mode is supported and can be properly enabled based on the
|
|
return value of `pcie_enable_tph()`.
|
|
|
|
To disable TPH, use the following function::
|
|
|
|
void pcie_disable_tph(struct pci_dev *pdev);
|
|
|
|
Manage ST
|
|
---------
|
|
|
|
Steering Tags are platform specific. PCIe spec does not specify where STs
|
|
are from. Instead PCI Firmware Specification defines an ACPI _DSM method
|
|
(see the `Revised _DSM for Cache Locality TPH Features ECN
|
|
<https://members.pcisig.com/wg/PCI-SIG/document/15470>`_) for retrieving
|
|
STs for a target memory of various properties. This method is what is
|
|
supported in this implementation.
|
|
|
|
To retrieve a Steering Tag for a target memory associated with a specific
|
|
CPU, use the following function::
|
|
|
|
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
|
|
unsigned int cpu_uid, u16 *tag);
|
|
|
|
The `type` argument is used to specify the memory type, either volatile
|
|
or persistent, of the target memory. The `cpu_uid` argument specifies the
|
|
CPU where the memory is associated to.
|
|
|
|
After the ST value is retrieved, the device driver can use the following
|
|
function to write the ST into the device::
|
|
|
|
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
|
|
u16 tag);
|
|
|
|
The `index` argument is the ST table entry index the ST tag will be
|
|
written into. `pcie_tph_set_st_entry()` will figure out the proper
|
|
location of ST table, either in the MSI-X table or in the TPH Extended
|
|
Capability space, and write the Steering Tag into the ST entry pointed by
|
|
the `index` argument.
|
|
|
|
It is completely up to the driver to decide how to use these TPH
|
|
functions. For example a network device driver can use the TPH APIs above
|
|
to update the Steering Tag when interrupt affinity of a RX/TX queue has
|
|
been changed. Here is a sample code for IRQ affinity notifier:
|
|
|
|
.. code-block:: c
|
|
|
|
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;
|
|
}
|
|
|
|
Disable TPH system-wide
|
|
-----------------------
|
|
|
|
There is a kernel command line option available to control TPH feature:
|
|
* "notph": TPH will be disabled for all endpoint devices.
|