x86/platform/uv: Update UV[23] platform code for SNC
authorSteve Wahl <steve.wahl@hpe.com>
Fri, 19 May 2023 19:07:52 +0000 (14:07 -0500)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 31 May 2023 16:35:00 +0000 (09:35 -0700)
Previous Sub-NUMA Clustering changes need not just a count of blades
present, but a count that includes any missing ids for blades not
present; in other words, the range from lowest to highest blade id.

Signed-off-by: Steve Wahl <steve.wahl@hpe.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lore.kernel.org/all/20230519190752.3297140-9-steve.wahl%40hpe.com
arch/x86/kernel/apic/x2apic_uv_x.c

index 1836330..d9384d5 100644 (file)
@@ -1462,11 +1462,37 @@ static int __init decode_uv_systab(void)
        return 0;
 }
 
+/*
+ * Given a bitmask 'bits' representing presnt blades, numbered
+ * starting at 'base', masking off unused high bits of blade number
+ * with 'mask', update the minimum and maximum blade numbers that we
+ * have found.  (Masking with 'mask' necessary because of BIOS
+ * treatment of system partitioning when creating this table we are
+ * interpreting.)
+ */
+static inline void blade_update_min_max(unsigned long bits, int base, int mask, int *min, int *max)
+{
+       int first, last;
+
+       if (!bits)
+               return;
+       first = (base + __ffs(bits)) & mask;
+       last =  (base + __fls(bits)) & mask;
+
+       if (*min > first)
+               *min = first;
+       if (*max < last)
+               *max = last;
+}
+
 /* Set up physical blade translations from UVH_NODE_PRESENT_TABLE */
 static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
 {
        unsigned long np;
        int i, uv_pb = 0;
+       int sock_min = INT_MAX, sock_max = -1, s_mask;
+
+       s_mask = (1 << uv_cpuid.n_skt) - 1;
 
        if (UVH_NODE_PRESENT_TABLE) {
                pr_info("UV: NODE_PRESENT_DEPTH = %d\n",
@@ -1474,23 +1500,31 @@ static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
                for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
                        np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
                        pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np);
-                       uv_pb += hweight64(np);
+                       blade_update_min_max(np, i * 64, s_mask, &sock_min, &sock_max);
                }
        }
        if (UVH_NODE_PRESENT_0) {
                np = uv_read_local_mmr(UVH_NODE_PRESENT_0);
                pr_info("UV: NODE_PRESENT_0 = 0x%016lx\n", np);
-               uv_pb += hweight64(np);
+               blade_update_min_max(np, 0, s_mask, &sock_min, &sock_max);
        }
        if (UVH_NODE_PRESENT_1) {
                np = uv_read_local_mmr(UVH_NODE_PRESENT_1);
                pr_info("UV: NODE_PRESENT_1 = 0x%016lx\n", np);
-               uv_pb += hweight64(np);
+               blade_update_min_max(np, 64, s_mask, &sock_min, &sock_max);
+       }
+
+       /* Only update if we actually found some bits indicating blades present */
+       if (sock_max >= sock_min) {
+               _min_socket = sock_min;
+               _max_socket = sock_max;
+               uv_pb = sock_max - sock_min + 1;
        }
        if (uv_possible_blades != uv_pb)
                uv_possible_blades = uv_pb;
 
-       pr_info("UV: number nodes/possible blades %d\n", uv_pb);
+       pr_info("UV: number nodes/possible blades %d (%d - %d)\n",
+               uv_pb, sock_min, sock_max);
 }
 
 static int __init alloc_conv_table(int num_elem, unsigned short **table)