]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI/TPH: Pass ACPI Processor UID to Cache Locality _DSM
authorChengwen Feng <fengchengwen@huawei.com>
Wed, 1 Apr 2026 08:16:40 +0000 (16:16 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 6 Apr 2026 14:55:16 +0000 (16:55 +0200)
pcie_tph_get_cpu_st() uses the Query Cache Locality Features _DSM [1]
to retrieve the TPH Steering Tag for memory associated with the CPU
identified by its "cpu_uid" parameter, a Linux logical CPU ID.

The _DSM requires an ACPI Processor UID, which pcie_tph_get_cpu_st()
previously assumed was the same as the Linux logical CPU ID. This is
true on x86 but not on arm64, so pcie_tph_get_cpu_st() returned the
wrong Steering Tag, resulting in incorrect TPH functionality on arm64.

Convert the Linux logical CPU ID to the ACPI Processor UID with
acpi_get_cpu_uid() before passing it to the _DSM. Additionally, rename
the pcie_tph_get_cpu_st() parameter from "cpu_uid" to "cpu" to reflect
that it represents a logical CPU ID (not an ACPI Processor UID).

[1] According to ECN_TPH-ST_Revision_20200924
    (https://members.pcisig.com/wg/PCI-SIG/document/15470), the input
    is defined as: "If the target is a processor, then this field
    represents the ACPI Processor UID of the processor as specified in
    the MADT. If the target is a processor container, then this field
    represents the ACPI Processor UID of the processor container as
    specified in the PPTT."

Fixes: d2e8a34876ce ("PCI/TPH: Add Steering Tag support")
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260401081640.26875-9-fengchengwen@huawei.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Documentation/PCI/tph.rst
drivers/pci/tph.c
include/linux/pci-tph.h

index e8993be64fd64df0f6ac22b98d060af63e2edffa..b6cf22b9bd90a57d53509210b33c90cc51853fc5 100644 (file)
@@ -79,10 +79,10 @@ 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);
+                          unsigned int cpu, 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
+or persistent, of the target memory. The `cpu` argument specifies the
 CPU where the memory is associated to.
 
 After the ST value is retrieved, the device driver can use the following
index ca4f97be75389d8e2c52eeb511fab266e075a63b..b67c9ad14bdaada6aac0e0d67c14c2872a8502fe 100644 (file)
@@ -236,21 +236,27 @@ static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag)
  * with a specific CPU
  * @pdev: PCI device
  * @mem_type: target memory type (volatile or persistent RAM)
- * @cpu_uid: associated CPU id
+ * @cpu: associated CPU id
  * @tag: Steering Tag to be returned
  *
  * Return the Steering Tag for a target memory that is associated with a
- * specific CPU as indicated by cpu_uid.
+ * specific CPU as indicated by cpu.
  *
  * Return: 0 if success, otherwise negative value (-errno)
  */
 int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
-                       unsigned int cpu_uid, u16 *tag)
+                       unsigned int cpu, u16 *tag)
 {
 #ifdef CONFIG_ACPI
        struct pci_dev *rp;
        acpi_handle rp_acpi_handle;
        union st_info info;
+       u32 cpu_uid;
+       int ret;
+
+       ret = acpi_get_cpu_uid(cpu, &cpu_uid);
+       if (ret != 0)
+               return ret;
 
        rp = pcie_find_root_port(pdev);
        if (!rp || !rp->bus || !rp->bus->bridge)
@@ -265,9 +271,9 @@ int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
 
        *tag = tph_extract_tag(mem_type, pdev->tph_req_type, &info);
 
-       pci_dbg(pdev, "get steering tag: mem_type=%s, cpu_uid=%d, tag=%#04x\n",
+       pci_dbg(pdev, "get steering tag: mem_type=%s, cpu=%d, tag=%#04x\n",
                (mem_type == TPH_MEM_TYPE_VM) ? "volatile" : "persistent",
-               cpu_uid, *tag);
+               cpu, *tag);
 
        return 0;
 #else
index ba28140ce6707621340064bce1d3d97f4c613bdd..be68cd17f2f833dc7efdefb5de5f97f7cb56ed30 100644 (file)
@@ -25,7 +25,7 @@ int pcie_tph_set_st_entry(struct pci_dev *pdev,
                          unsigned int index, u16 tag);
 int pcie_tph_get_cpu_st(struct pci_dev *dev,
                        enum tph_mem_type mem_type,
-                       unsigned int cpu_uid, u16 *tag);
+                       unsigned int cpu, u16 *tag);
 void pcie_disable_tph(struct pci_dev *pdev);
 int pcie_enable_tph(struct pci_dev *pdev, int mode);
 u16 pcie_tph_get_st_table_size(struct pci_dev *pdev);
@@ -36,7 +36,7 @@ static inline int pcie_tph_set_st_entry(struct pci_dev *pdev,
 { return -EINVAL; }
 static inline int pcie_tph_get_cpu_st(struct pci_dev *dev,
                                      enum tph_mem_type mem_type,
-                                     unsigned int cpu_uid, u16 *tag)
+                                     unsigned int cpu, u16 *tag)
 { return -EINVAL; }
 static inline void pcie_disable_tph(struct pci_dev *pdev) { }
 static inline int pcie_enable_tph(struct pci_dev *pdev, int mode)