]> 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)
committerPeter Zijlstra <peterz@infradead.org>
Tue, 7 Apr 2026 07:05:29 +0000 (09:05 +0200)
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
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore_snbep.c

index 786bd51a0d89c4dd8e79f2c0f2b77d61dffbd7d9..e9cc1ba921c5ed4c49b108b4571e58811e97ad28 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 0a1d08136cc1082429324df7e8a1fc63e9b7b99e..a4b337bf83c0b1e44ff696b22ae865c4aeb9aac0 100644 (file)
@@ -1459,13 +1459,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;
-                       }
                }
        }
 
@@ -6420,7 +6414,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;
 
@@ -6444,6 +6438,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.