perf/x86/intel/uncore: With > 8 nodes, get pci bus die id from NUMA info
authorSteve Wahl <steve.wahl@hpe.com>
Fri, 8 Jan 2021 15:35:49 +0000 (09:35 -0600)
committerPeter Zijlstra <peterz@infradead.org>
Thu, 14 Jan 2021 10:20:14 +0000 (11:20 +0100)
The registers used to determine which die a pci bus belongs to don't
contain enough information to uniquely specify more than 8 dies, so
when more than 8 dies are present, use NUMA information instead.

Continue to use the previous method for 8 or fewer because it
works there, and covers cases of NUMA being disabled.

Signed-off-by: Steve Wahl <steve.wahl@hpe.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lkml.kernel.org/r/20210108153549.108989-3-steve.wahl@hpe.com
arch/x86/events/intel/uncore_snbep.c

index 2d7014d..b79951d 100644 (file)
@@ -1370,40 +1370,77 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
                if (!ubox_dev)
                        break;
                bus = ubox_dev->bus->number;
-               /* get the Node ID of the local register */
-               err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
-               if (err)
-                       break;
-               nodeid = config & NODE_ID_MASK;
-               /* get the Node ID mapping */
-               err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
-               if (err)
-                       break;
+               /*
+                * The nodeid and idmap registers only contain enough
+                * information to handle 8 nodes.  On systems with more
+                * than 8 nodes, we need to rely on NUMA information,
+                * filled in from BIOS supplied information, to determine
+                * the topology.
+                */
+               if (nr_node_ids <= 8) {
+                       /* get the Node ID of the local register */
+                       err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
+                       if (err)
+                               break;
+                       nodeid = config & NODE_ID_MASK;
+                       /* get the Node ID mapping */
+                       err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
+                       if (err)
+                               break;
 
-               segment = pci_domain_nr(ubox_dev->bus);
-               raw_spin_lock(&pci2phy_map_lock);
-               map = __find_pci2phy_map(segment);
-               if (!map) {
+                       segment = pci_domain_nr(ubox_dev->bus);
+                       raw_spin_lock(&pci2phy_map_lock);
+                       map = __find_pci2phy_map(segment);
+                       if (!map) {
+                               raw_spin_unlock(&pci2phy_map_lock);
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       /*
+                        * every three bits in the Node ID mapping register maps
+                        * to a particular node.
+                        */
+                       for (i = 0; i < 8; i++) {
+                               if (nodeid == ((config >> (3 * i)) & 0x7)) {
+                                       if (topology_max_die_per_package() > 1)
+                                               die_id = i;
+                                       else
+                                               die_id = topology_phys_to_logical_pkg(i);
+                                       map->pbus_to_dieid[bus] = die_id;
+                                       break;
+                               }
+                       }
                        raw_spin_unlock(&pci2phy_map_lock);
-                       err = -ENOMEM;
-                       break;
-               }
+               } else {
+                       int node = pcibus_to_node(ubox_dev->bus);
+                       int cpu;
+
+                       segment = pci_domain_nr(ubox_dev->bus);
+                       raw_spin_lock(&pci2phy_map_lock);
+                       map = __find_pci2phy_map(segment);
+                       if (!map) {
+                               raw_spin_unlock(&pci2phy_map_lock);
+                               err = -ENOMEM;
+                               break;
+                       }
 
-               /*
-                * every three bits in the Node ID mapping register maps
-                * to a particular node.
-                */
-               for (i = 0; i < 8; i++) {
-                       if (nodeid == ((config >> (3 * i)) & 0x7)) {
-                               if (topology_max_die_per_package() > 1)
-                                       die_id = i;
-                               else
-                                       die_id = topology_phys_to_logical_pkg(i);
-                               map->pbus_to_dieid[bus] = die_id;
+                       die_id = -1;
+                       for_each_cpu(cpu, cpumask_of_pcibus(ubox_dev->bus)) {
+                               struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+                               if (c->initialized && cpu_to_node(cpu) == node) {
+                                       map->pbus_to_dieid[bus] = die_id = c->logical_die_id;
+                                       break;
+                               }
+                       }
+                       raw_spin_unlock(&pci2phy_map_lock);
+
+                       if (WARN_ON_ONCE(die_id == -1)) {
+                               err = -EINVAL;
                                break;
                        }
                }
-               raw_spin_unlock(&pci2phy_map_lock);
        }
 
        if (!err) {