Skip to content

Commit 5c14386

Browse files
author
CKI KWF Bot
committed
Merge: CNB101: PCI: Add TLP Processing Hints (TPH) support
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/990 JIRA: https://issues.redhat.com/browse/RHEL-94973 Commits: ``` f69767a ("PCI: Add TLP Processing Hints (TPH) support") d2e8a34 ("PCI/TPH: Add Steering Tag support") 48d0fd2 ("PCI/TPH: Add TPH documentation") 6f64b83 ("PCI/TPH: Restore TPH Requester Enable correctly") ``` Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> Signed-off-by: Ivan Vecera <ivecera@redhat.com> Approved-by: John W. Linville <linville@redhat.com> Approved-by: Petr Oros <poros@redhat.com> Approved-by: mheib <mheib@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents ffef9db + db57b8f commit 5c14386

File tree

14 files changed

+795
-8
lines changed

14 files changed

+795
-8
lines changed

Documentation/PCI/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ PCI Bus Subsystem
1818
pcieaer-howto
1919
endpoint/index
2020
boot-interrupts
21+
tph

Documentation/PCI/tph.rst

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
4+
===========
5+
TPH Support
6+
===========
7+
8+
:Copyright: 2024 Advanced Micro Devices, Inc.
9+
:Authors: - Eric van Tassell <eric.vantassell@amd.com>
10+
- Wei Huang <wei.huang2@amd.com>
11+
12+
13+
Overview
14+
========
15+
16+
TPH (TLP Processing Hints) is a PCIe feature that allows endpoint devices
17+
to provide optimization hints for requests that target memory space.
18+
These hints, in a format called Steering Tags (STs), are embedded in the
19+
requester's TLP headers, enabling the system hardware, such as the Root
20+
Complex, to better manage platform resources for these requests.
21+
22+
For example, on platforms with TPH-based direct data cache injection
23+
support, an endpoint device can include appropriate STs in its DMA
24+
traffic to specify which cache the data should be written to. This allows
25+
the CPU core to have a higher probability of getting data from cache,
26+
potentially improving performance and reducing latency in data
27+
processing.
28+
29+
30+
How to Use TPH
31+
==============
32+
33+
TPH is presented as an optional extended capability in PCIe. The Linux
34+
kernel handles TPH discovery during boot, but it is up to the device
35+
driver to request TPH enablement if it is to be utilized. Once enabled,
36+
the driver uses the provided API to obtain the Steering Tag for the
37+
target memory and to program the ST into the device's ST table.
38+
39+
Enable TPH support in Linux
40+
---------------------------
41+
42+
To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
43+
enabled.
44+
45+
Manage TPH
46+
----------
47+
48+
To enable TPH for a device, use the following function::
49+
50+
int pcie_enable_tph(struct pci_dev *pdev, int mode);
51+
52+
This function enables TPH support for device with a specific ST mode.
53+
Current supported modes include:
54+
55+
* PCI_TPH_ST_NS_MODE - NO ST Mode
56+
* PCI_TPH_ST_IV_MODE - Interrupt Vector Mode
57+
* PCI_TPH_ST_DS_MODE - Device Specific Mode
58+
59+
`pcie_enable_tph()` checks whether the requested mode is actually
60+
supported by the device before enabling. The device driver can figure out
61+
which TPH mode is supported and can be properly enabled based on the
62+
return value of `pcie_enable_tph()`.
63+
64+
To disable TPH, use the following function::
65+
66+
void pcie_disable_tph(struct pci_dev *pdev);
67+
68+
Manage ST
69+
---------
70+
71+
Steering Tags are platform specific. PCIe spec does not specify where STs
72+
are from. Instead PCI Firmware Specification defines an ACPI _DSM method
73+
(see the `Revised _DSM for Cache Locality TPH Features ECN
74+
<https://members.pcisig.com/wg/PCI-SIG/document/15470>`_) for retrieving
75+
STs for a target memory of various properties. This method is what is
76+
supported in this implementation.
77+
78+
To retrieve a Steering Tag for a target memory associated with a specific
79+
CPU, use the following function::
80+
81+
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
82+
unsigned int cpu_uid, u16 *tag);
83+
84+
The `type` argument is used to specify the memory type, either volatile
85+
or persistent, of the target memory. The `cpu_uid` argument specifies the
86+
CPU where the memory is associated to.
87+
88+
After the ST value is retrieved, the device driver can use the following
89+
function to write the ST into the device::
90+
91+
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
92+
u16 tag);
93+
94+
The `index` argument is the ST table entry index the ST tag will be
95+
written into. `pcie_tph_set_st_entry()` will figure out the proper
96+
location of ST table, either in the MSI-X table or in the TPH Extended
97+
Capability space, and write the Steering Tag into the ST entry pointed by
98+
the `index` argument.
99+
100+
It is completely up to the driver to decide how to use these TPH
101+
functions. For example a network device driver can use the TPH APIs above
102+
to update the Steering Tag when interrupt affinity of a RX/TX queue has
103+
been changed. Here is a sample code for IRQ affinity notifier:
104+
105+
.. code-block:: c
106+
107+
static void irq_affinity_notified(struct irq_affinity_notify *notify,
108+
const cpumask_t *mask)
109+
{
110+
struct drv_irq *irq;
111+
unsigned int cpu_id;
112+
u16 tag;
113+
114+
irq = container_of(notify, struct drv_irq, affinity_notify);
115+
cpumask_copy(irq->cpu_mask, mask);
116+
117+
/* Pick a right CPU as the target - here is just an example */
118+
cpu_id = cpumask_first(irq->cpu_mask);
119+
120+
if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
121+
&tag))
122+
return;
123+
124+
if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
125+
return;
126+
}
127+
128+
Disable TPH system-wide
129+
-----------------------
130+
131+
There is a kernel command line option available to control TPH feature:
132+
* "notph": TPH will be disabled for all endpoint devices.

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4689,6 +4689,10 @@
46894689
nomio [S390] Do not use MIO instructions.
46904690
norid [S390] ignore the RID field and force use of
46914691
one PCI domain per PCI function
4692+
notph [PCIE] If the PCIE_TPH kernel config parameter
4693+
is enabled, this kernel boot option can be used
4694+
to disable PCIe TLP Processing Hints support
4695+
system-wide.
46924696

46934697
pcie_aspm= [PCIE] Forcibly enable or ignore PCIe Active State Power
46944698
Management.

Documentation/driver-api/pci/pci.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ PCI Support Library
4646
.. kernel-doc:: drivers/pci/pci-sysfs.c
4747
:internal:
4848

49+
.. kernel-doc:: drivers/pci/tph.c
50+
:export:
51+
4952
PCI Hotplug Support Library
5053
---------------------------
5154

drivers/pci/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ config PCI_PASID
173173

174174
If unsure, say N.
175175

176+
config PCIE_TPH
177+
bool "TLP Processing Hints"
178+
help
179+
This option adds support for PCIe TLP Processing Hints (TPH).
180+
TPH allows endpoint devices to provide optimization hints, such as
181+
desired caching behavior, for requests that target memory space.
182+
These hints, called Steering Tags, can empower the system hardware
183+
to optimize the utilization of platform resources.
184+
176185
config PCI_P2PDMA
177186
bool "PCI peer-to-peer transfer support"
178187
depends on ZONE_DEVICE

drivers/pci/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ obj-$(CONFIG_VGA_ARB) += vgaarb.o
3636
obj-$(CONFIG_PCI_DOE) += doe.o
3737
obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o
3838
obj-$(CONFIG_PCI_NPEM) += npem.o
39+
obj-$(CONFIG_PCIE_TPH) += tph.o
3940

4041
# Endpoint library must be initialized before its users
4142
obj-$(CONFIG_PCI_ENDPOINT) += endpoint/

drivers/pci/pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,7 @@ int pci_save_state(struct pci_dev *dev)
18111811
pci_save_dpc_state(dev);
18121812
pci_save_aer_state(dev);
18131813
pci_save_ptm_state(dev);
1814+
pci_save_tph_state(dev);
18141815
return pci_save_vc_state(dev);
18151816
}
18161817
EXPORT_SYMBOL(pci_save_state);
@@ -1916,6 +1917,7 @@ void pci_restore_state(struct pci_dev *dev)
19161917
pci_restore_rebar_state(dev);
19171918
pci_restore_dpc_state(dev);
19181919
pci_restore_ptm_state(dev);
1920+
pci_restore_tph_state(dev);
19191921

19201922
pci_aer_clear_status(dev);
19211923
pci_restore_aer_state(dev);
@@ -6809,6 +6811,8 @@ static int __init pci_setup(char *str)
68096811
pci_no_domains();
68106812
} else if (!strncmp(str, "noari", 5)) {
68116813
pcie_ari_disabled = true;
6814+
} else if (!strncmp(str, "notph", 5)) {
6815+
pci_no_tph();
68126816
} else if (!strncmp(str, "cbiosize=", 9)) {
68136817
pci_cardbus_io_size = memparse(str + 9, &str);
68146818
} else if (!strncmp(str, "cbmemsize=", 10)) {

drivers/pci/pci.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,18 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
649649

650650
#endif /* CONFIG_PCI_IOV */
651651

652+
#ifdef CONFIG_PCIE_TPH
653+
void pci_restore_tph_state(struct pci_dev *dev);
654+
void pci_save_tph_state(struct pci_dev *dev);
655+
void pci_no_tph(void);
656+
void pci_tph_init(struct pci_dev *dev);
657+
#else
658+
static inline void pci_restore_tph_state(struct pci_dev *dev) { }
659+
static inline void pci_save_tph_state(struct pci_dev *dev) { }
660+
static inline void pci_no_tph(void) { }
661+
static inline void pci_tph_init(struct pci_dev *dev) { }
662+
#endif
663+
652664
#ifdef CONFIG_PCIE_PTM
653665
void pci_ptm_init(struct pci_dev *dev);
654666
void pci_save_ptm_state(struct pci_dev *dev);

drivers/pci/probe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2564,6 +2564,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
25642564
pci_dpc_init(dev); /* Downstream Port Containment */
25652565
pci_rcec_init(dev); /* Root Complex Event Collector */
25662566
pci_doe_init(dev); /* Data Object Exchange */
2567+
pci_tph_init(dev); /* TLP Processing Hints */
25672568

25682569
pcie_report_downtraining(dev);
25692570
pci_init_reset_methods(dev);

0 commit comments

Comments
 (0)