|
@@ -6128,6 +6128,7 @@ static void claim_allocations(int cpu, struct sched_domain *sd)
|
|
|
|
|
|
#ifdef CONFIG_NUMA
|
|
#ifdef CONFIG_NUMA
|
|
static int sched_domains_numa_levels;
|
|
static int sched_domains_numa_levels;
|
|
|
|
+enum numa_topology_type sched_numa_topology_type;
|
|
static int *sched_domains_numa_distance;
|
|
static int *sched_domains_numa_distance;
|
|
int sched_max_numa_distance;
|
|
int sched_max_numa_distance;
|
|
static struct cpumask ***sched_domains_numa_masks;
|
|
static struct cpumask ***sched_domains_numa_masks;
|
|
@@ -6316,6 +6317,56 @@ bool find_numa_distance(int distance)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * A system can have three types of NUMA topology:
|
|
|
|
+ * NUMA_DIRECT: all nodes are directly connected, or not a NUMA system
|
|
|
|
+ * NUMA_GLUELESS_MESH: some nodes reachable through intermediary nodes
|
|
|
|
+ * NUMA_BACKPLANE: nodes can reach other nodes through a backplane
|
|
|
|
+ *
|
|
|
|
+ * The difference between a glueless mesh topology and a backplane
|
|
|
|
+ * topology lies in whether communication between not directly
|
|
|
|
+ * connected nodes goes through intermediary nodes (where programs
|
|
|
|
+ * could run), or through backplane controllers. This affects
|
|
|
|
+ * placement of programs.
|
|
|
|
+ *
|
|
|
|
+ * The type of topology can be discerned with the following tests:
|
|
|
|
+ * - If the maximum distance between any nodes is 1 hop, the system
|
|
|
|
+ * is directly connected.
|
|
|
|
+ * - If for two nodes A and B, located N > 1 hops away from each other,
|
|
|
|
+ * there is an intermediary node C, which is < N hops away from both
|
|
|
|
+ * nodes A and B, the system is a glueless mesh.
|
|
|
|
+ */
|
|
|
|
+static void init_numa_topology_type(void)
|
|
|
|
+{
|
|
|
|
+ int a, b, c, n;
|
|
|
|
+
|
|
|
|
+ n = sched_max_numa_distance;
|
|
|
|
+
|
|
|
|
+ if (n <= 1)
|
|
|
|
+ sched_numa_topology_type = NUMA_DIRECT;
|
|
|
|
+
|
|
|
|
+ for_each_online_node(a) {
|
|
|
|
+ for_each_online_node(b) {
|
|
|
|
+ /* Find two nodes furthest removed from each other. */
|
|
|
|
+ if (node_distance(a, b) < n)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ /* Is there an intermediary node between a and b? */
|
|
|
|
+ for_each_online_node(c) {
|
|
|
|
+ if (node_distance(a, c) < n &&
|
|
|
|
+ node_distance(b, c) < n) {
|
|
|
|
+ sched_numa_topology_type =
|
|
|
|
+ NUMA_GLUELESS_MESH;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sched_numa_topology_type = NUMA_BACKPLANE;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void sched_init_numa(void)
|
|
static void sched_init_numa(void)
|
|
{
|
|
{
|
|
int next_distance, curr_distance = node_distance(0, 0);
|
|
int next_distance, curr_distance = node_distance(0, 0);
|
|
@@ -6449,6 +6500,8 @@ static void sched_init_numa(void)
|
|
|
|
|
|
sched_domains_numa_levels = level;
|
|
sched_domains_numa_levels = level;
|
|
sched_max_numa_distance = sched_domains_numa_distance[level - 1];
|
|
sched_max_numa_distance = sched_domains_numa_distance[level - 1];
|
|
|
|
+
|
|
|
|
+ init_numa_topology_type();
|
|
}
|
|
}
|
|
|
|
|
|
static void sched_domains_numa_masks_set(int cpu)
|
|
static void sched_domains_numa_masks_set(int cpu)
|