<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>12. TPH Support — The Linux Kernel documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=3918102e" />
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Assorted Miscellaneous Devices Documentation" href="../misc-devices/index.html" />
<link rel="prev" title="11. Boot Interrupts" href="boot-interrupts.html" />
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.svg" alt="Logo of The Linux Kernel"/>
</a></p>
<h1 class="logo"><a href="../index.html">The Linux Kernel</a></h1>
<p class="blurb">6.18.50</p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<p>
<h3 class="kernel-toc-contents">Contents</h3>
<input type="checkbox" class="kernel-toc-toggle" id = "kernel-toc-toggle" checked>
<label class="kernel-toc-title" for="kernel-toc-toggle"></label>
<div class="kerneltoc" id="kerneltoc">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../process/development-process.html">Development process</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/submitting-patches.html">Submitting patches</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/code-of-conduct.html">Code of conduct</a></li>
<li class="toctree-l1"><a class="reference internal" href="../maintainer/index.html">Maintainer handbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/index.html">All development-process docs</a></li>
</ul>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../core-api/index.html">Core API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../driver-api/index.html">Driver APIs</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../subsystem-apis.html">Subsystems</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#core-subsystems">Core subsystems</a></li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#human-interfaces">Human interfaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#networking-interfaces">Networking interfaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#storage-interfaces">Storage interfaces</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="../subsystem-apis.html#other-subsystems">Other subsystems</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="../accounting/index.html">Accounting</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cpu-freq/index.html">CPUFreq - CPU frequency and voltage scaling code in the Linux(TM) kernel</a></li>
<li class="toctree-l3"><a class="reference internal" href="../edac/index.html">EDAC Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../fpga/index.html">FPGA</a></li>
<li class="toctree-l3"><a class="reference internal" href="../i2c/index.html">I2C/SMBus Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../iio/index.html">Industrial I/O</a></li>
<li class="toctree-l3"><a class="reference internal" href="../pcmcia/index.html">PCMCIA</a></li>
<li class="toctree-l3"><a class="reference internal" href="../spi/index.html">Serial Peripheral Interface (SPI)</a></li>
<li class="toctree-l3"><a class="reference internal" href="../w1/index.html">1-Wire Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../watchdog/index.html">Watchdog Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="../virt/index.html">Virtualization Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="../hwmon/index.html">Hardware Monitoring</a></li>
<li class="toctree-l3"><a class="reference internal" href="../accel/index.html">Compute Accelerators</a></li>
<li class="toctree-l3"><a class="reference internal" href="../security/index.html">Security Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../crypto/index.html">Crypto API</a></li>
<li class="toctree-l3"><a class="reference internal" href="../bpf/index.html">BPF Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../usb/index.html">USB support</a></li>
<li class="toctree-l3 current"><a class="reference internal" href="index.html">PCI Bus Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../misc-devices/index.html">Assorted Miscellaneous Devices Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../peci/index.html">PECI Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../wmi/index.html">WMI Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../tee/index.html">TEE Subsystem</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../locking/index.html">Locking</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../process/license-rules.html">Licensing rules</a></li>
<li class="toctree-l1"><a class="reference internal" href="../doc-guide/index.html">Writing documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dev-tools/index.html">Development tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dev-tools/testing-overview.html">Testing guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../kernel-hacking/index.html">Hacking guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../trace/index.html">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../fault-injection/index.html">Fault injection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../livepatch/index.html">Livepatching</a></li>
<li class="toctree-l1"><a class="reference internal" href="../rust/index.html">Rust</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../admin-guide/index.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../kbuild/index.html">Build system</a></li>
<li class="toctree-l1"><a class="reference internal" href="../admin-guide/reporting-issues.html">Reporting issues</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tools/index.html">Userspace tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../userspace-api/index.html">Userspace API</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../firmware-guide/index.html">Firmware</a></li>
<li class="toctree-l1"><a class="reference internal" href="../devicetree/index.html">Firmware and Devicetree</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../arch/index.html">CPU architectures</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../staging/index.html">Unsorted documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../translations/index.html">Translations</a></li>
</ul>
</div>
<script type="text/javascript"> <!--
var sbar = document.getElementsByClassName("sphinxsidebar")[0];
let currents = document.getElementsByClassName("current")
if (currents.length) {
sbar.scrollTop = currents[currents.length - 1].offsetTop;
}
--> </script>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/PCI/tph.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="tph-support">
<h1><span class="section-number">12. </span>TPH Support<a class="headerlink" href="#tph-support" title="Link to this heading">¶</a></h1>
<dl class="field-list simple">
<dt class="field-odd">Copyright<span class="colon">:</span></dt>
<dd class="field-odd"><p>2024 Advanced Micro Devices, Inc.</p>
</dd>
<dt class="field-even">Authors<span class="colon">:</span></dt>
<dd class="field-even"><ul class="simple">
<li><p>Eric van Tassell <<a class="reference external" href="mailto:eric.vantassell%40amd.com">eric<span>.</span>vantassell<span>@</span>amd<span>.</span>com</a>></p></li>
<li><p>Wei Huang <<a class="reference external" href="mailto:wei.huang2%40amd.com">wei<span>.</span>huang2<span>@</span>amd<span>.</span>com</a>></p></li>
</ul>
</dd>
</dl>
<section id="overview">
<h2><span class="section-number">12.1. </span>Overview<a class="headerlink" href="#overview" title="Link to this heading">¶</a></h2>
<p>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.</p>
<p>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.</p>
</section>
<section id="how-to-use-tph">
<h2><span class="section-number">12.2. </span>How to Use TPH<a class="headerlink" href="#how-to-use-tph" title="Link to this heading">¶</a></h2>
<p>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.</p>
<section id="enable-tph-support-in-linux">
<h3><span class="section-number">12.2.1. </span>Enable TPH support in Linux<a class="headerlink" href="#enable-tph-support-in-linux" title="Link to this heading">¶</a></h3>
<p>To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
enabled.</p>
</section>
<section id="manage-tph">
<h3><span class="section-number">12.2.2. </span>Manage TPH<a class="headerlink" href="#manage-tph" title="Link to this heading">¶</a></h3>
<p>To enable TPH for a device, use the following function:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int pcie_enable_tph(struct pci_dev *pdev, int mode);
</pre></div>
</div>
<p>This function enables TPH support for device with a specific ST mode.
Current supported modes include:</p>
<blockquote>
<div><ul class="simple">
<li><p>PCI_TPH_ST_NS_MODE - NO ST Mode</p></li>
<li><p>PCI_TPH_ST_IV_MODE - Interrupt Vector Mode</p></li>
<li><p>PCI_TPH_ST_DS_MODE - Device Specific Mode</p></li>
</ul>
</div></blockquote>
<p><cite><a class="reference internal" href="../driver-api/pci/pci.html#c.pcie_enable_tph" title="pcie_enable_tph"><code class="xref c c-func docutils literal notranslate"><span class="pre">pcie_enable_tph()</span></code></a></cite> 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 <cite><a class="reference internal" href="../driver-api/pci/pci.html#c.pcie_enable_tph" title="pcie_enable_tph"><code class="xref c c-func docutils literal notranslate"><span class="pre">pcie_enable_tph()</span></code></a></cite>.</p>
<p>To disable TPH, use the following function:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>void pcie_disable_tph(struct pci_dev *pdev);
</pre></div>
</div>
</section>
<section id="manage-st">
<h3><span class="section-number">12.2.3. </span>Manage ST<a class="headerlink" href="#manage-st" title="Link to this heading">¶</a></h3>
<p>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 <a class="reference external" href="https://members.pcisig.com/wg/PCI-SIG/document/15470">Revised _DSM for Cache Locality TPH Features ECN</a>) for retrieving
STs for a target memory of various properties. This method is what is
supported in this implementation.</p>
<p>To retrieve a Steering Tag for a target memory associated with a specific
CPU, use the following function:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
unsigned int cpu_uid, u16 *tag);
</pre></div>
</div>
<p>The <cite>type</cite> argument is used to specify the memory type, either volatile
or persistent, of the target memory. The <cite>cpu_uid</cite> argument specifies the
CPU where the memory is associated to.</p>
<p>After the ST value is retrieved, the device driver can use the following
function to write the ST into the device:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
u16 tag);
</pre></div>
</div>
<p>The <cite>index</cite> argument is the ST table entry index the ST tag will be
written into. <cite><a class="reference internal" href="../driver-api/pci/pci.html#c.pcie_tph_set_st_entry" title="pcie_tph_set_st_entry"><code class="xref c c-func docutils literal notranslate"><span class="pre">pcie_tph_set_st_entry()</span></code></a></cite> 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 <cite>index</cite> argument.</p>
<p>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:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">irq_affinity_notified</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">irq_affinity_notify</span><span class="w"> </span><span class="o">*</span><span class="n">notify</span><span class="p">,</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">cpumask_t</span><span class="w"> </span><span class="o">*</span><span class="n">mask</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">drv_irq</span><span class="w"> </span><span class="o">*</span><span class="n">irq</span><span class="p">;</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">cpu_id</span><span class="p">;</span>
<span class="w"> </span><span class="n">u16</span><span class="w"> </span><span class="n">tag</span><span class="p">;</span>
<span class="w"> </span><span class="n">irq</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">container_of</span><span class="p">(</span><span class="n">notify</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">drv_irq</span><span class="p">,</span><span class="w"> </span><span class="n">affinity_notify</span><span class="p">);</span>
<span class="w"> </span><span class="n">cpumask_copy</span><span class="p">(</span><span class="n">irq</span><span class="o">-></span><span class="n">cpu_mask</span><span class="p">,</span><span class="w"> </span><span class="n">mask</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Pick a right CPU as the target - here is just an example */</span>
<span class="w"> </span><span class="n">cpu_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cpumask_first</span><span class="p">(</span><span class="n">irq</span><span class="o">-></span><span class="n">cpu_mask</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pcie_tph_get_cpu_st</span><span class="p">(</span><span class="n">irq</span><span class="o">-></span><span class="n">pdev</span><span class="p">,</span><span class="w"> </span><span class="n">TPH_MEM_TYPE_VM</span><span class="p">,</span><span class="w"> </span><span class="n">cpu_id</span><span class="p">,</span>
<span class="w"> </span><span class="o">&</span><span class="n">tag</span><span class="p">))</span>
<span class="w"> </span><span class="k">return</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pcie_tph_set_st_entry</span><span class="p">(</span><span class="n">irq</span><span class="o">-></span><span class="n">pdev</span><span class="p">,</span><span class="w"> </span><span class="n">irq</span><span class="o">-></span><span class="n">msix_nr</span><span class="p">,</span><span class="w"> </span><span class="n">tag</span><span class="p">))</span>
<span class="w"> </span><span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="disable-tph-system-wide">
<h3><span class="section-number">12.2.4. </span>Disable TPH system-wide<a class="headerlink" href="#disable-tph-system-wide" title="Link to this heading">¶</a></h3>
<dl class="simple">
<dt>There is a kernel command line option available to control TPH feature:</dt><dd><ul class="simple">
<li><p>“notph”: TPH will be disabled for all endpoint devices.</p></li>
</ul>
</dd>
</dl>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©The kernel development community.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="../_sources/PCI/tph.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>