]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
perf/x86/intel/uncore: Fix die ID init and look up bugs
authorZide Chen <zide.chen@intel.com>
Fri, 13 Mar 2026 17:40:49 +0000 (10:40 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Apr 2026 11:30:43 +0000 (13:30 +0200)
[ Upstream commit a16d1ec4dd0cdcf689f324adde6067083bce9099 ]

In snbep_pci2phy_map_init(), in the nr_node_ids > 8 path,
uncore_device_to_die() may return -1 when all CPUs associated
with the UBOX device are offline.

Remove the WARN_ON_ONCE(die_id == -1) check for two reasons:

- The current code breaks out of the loop. This is incorrect because
  pci_get_device() does not guarantee iteration in domain or bus order,
  so additional UBOX devices may be skipped during the scan.

- Returning -EINVAL is incorrect, since marking offline buses with
  die_id == -1 is expected and should not be treated as an error.

Separately, when NUMA is disabled on a NUMA-capable platform,
pcibus_to_node() returns NUMA_NO_NODE, causing uncore_device_to_die()
to return -1 for all PCI devices.  As a result,
spr_update_device_location(), used on Intel SPR and EMR, ignores the
corresponding PMON units and does not add them to the RB tree.

Fix this by using uncore_pcibus_to_dieid(), which retrieves topology
from the UBOX GIDNIDMAP register and works regardless of whether NUMA
is enabled in Linux.  This requires snbep_pci2phy_map_init() to be
added in spr_uncore_pci_init().

Keep uncore_device_to_die() only for the nr_node_ids > 8 case, where
NUMA is expected to be enabled.

Fixes: 9a7832ce3d92 ("perf/x86/intel/uncore: With > 8 nodes, get pci bus die id from NUMA info")
Fixes: 65248a9a9ee1 ("perf/x86/uncore: Add a quirk for UPI on SPR")
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Tested-by: Steve Wahl <steve.wahl@hpe.com>
Link: https://patch.msgid.link/20260313174050.171704-4-zide.chen@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore_snbep.c

index e228e564b15ea6ace6e7ce4eae66f19579769ee9..8301a589d9a610767d3ed39ec9d9c88b4b58c3f3 100644 (file)
@@ -67,6 +67,7 @@ int uncore_die_to_segment(int die)
        return bus ? pci_domain_nr(bus) : -EINVAL;
 }
 
+/* Note: This API can only be used when NUMA information is available. */
 int uncore_device_to_die(struct pci_dev *dev)
 {
        int node = pcibus_to_node(dev->bus);
index a338ee01bb2427258cb15cbf5627918e1352d9c1..0182785cad1fe544f270839a8b3e1770688ec2cc 100644 (file)
@@ -1475,13 +1475,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
                        }
 
                        map->pbus_to_dieid[bus] = die_id = uncore_device_to_die(ubox_dev);
-
                        raw_spin_unlock(&pci2phy_map_lock);
-
-                       if (WARN_ON_ONCE(die_id == -1)) {
-                               err = -EINVAL;
-                               break;
-                       }
                }
        }
 
@@ -6533,7 +6527,7 @@ static void spr_update_device_location(int type_id)
 
        while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, dev)) != NULL) {
 
-               die = uncore_device_to_die(dev);
+               die = uncore_pcibus_to_dieid(dev->bus);
                if (die < 0)
                        continue;
 
@@ -6557,6 +6551,11 @@ static void spr_update_device_location(int type_id)
 
 int spr_uncore_pci_init(void)
 {
+       int ret = snbep_pci2phy_map_init(0x3250, SKX_CPUNODEID, SKX_GIDNIDMAP, true);
+
+       if (ret)
+               return ret;
+
        /*
         * The discovery table of UPI on some SPR variant is broken,
         * which impacts the detection of both UPI and M3UPI uncore PMON.