diff options
author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2015-08-05 05:23:53 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-08-07 03:57:38 -0400 |
commit | 7cde4910a5adcab62506eff49f4500053464fc8a (patch) | |
tree | e08f7692b733f4e9b57973d95ecda50795c0d981 | |
parent | 854508c0d0bbcf2f80fa1f79af5cb9ce219b2e9c (diff) |
s390/numa: make core to node mapping data dynamic
The core to node mapping data consumes about 2 KB bss data. To save memory
for the non-NUMA case, make the data dynamic. In addition change the
"core_to_node" array from "int" to "s32" which saves 1 KB also for the
NUMA case.
Suggested-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/numa/mode_emu.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/arch/s390/numa/mode_emu.c b/arch/s390/numa/mode_emu.c index 646cd94cff2f..7de4e2f780d7 100644 --- a/arch/s390/numa/mode_emu.c +++ b/arch/s390/numa/mode_emu.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/memblock.h> | 23 | #include <linux/memblock.h> |
24 | #include <linux/node.h> | 24 | #include <linux/node.h> |
25 | #include <linux/memory.h> | 25 | #include <linux/memory.h> |
26 | #include <linux/slab.h> | ||
26 | #include <asm/smp.h> | 27 | #include <asm/smp.h> |
27 | #include <asm/topology.h> | 28 | #include <asm/topology.h> |
28 | #include "numa_mode.h" | 29 | #include "numa_mode.h" |
@@ -56,26 +57,24 @@ static unsigned long emu_size; | |||
56 | * Node to core pinning information updates are protected by | 57 | * Node to core pinning information updates are protected by |
57 | * "sched_domains_mutex". | 58 | * "sched_domains_mutex". |
58 | */ | 59 | */ |
59 | /* Pinned core to node mapping */ | 60 | static struct { |
60 | static int cores_to_node_id[CONFIG_NR_CPUS]; | 61 | s32 to_node_id[CONFIG_NR_CPUS]; /* Pinned core to node mapping */ |
61 | /* Total number of pinned cores */ | 62 | int total; /* Total number of pinned cores */ |
62 | static int cores_total; | 63 | int per_node_target; /* Cores per node without extra cores */ |
63 | /* Number of cores per node without extra cores */ | 64 | int per_node[MAX_NUMNODES]; /* Number of cores pinned to node */ |
64 | static int cores_per_node_target; | 65 | } *emu_cores; |
65 | /* Number of cores pinned to node */ | ||
66 | static int cores_per_node[MAX_NUMNODES]; | ||
67 | 66 | ||
68 | /* | 67 | /* |
69 | * Pin a core to a node | 68 | * Pin a core to a node |
70 | */ | 69 | */ |
71 | static void pin_core_to_node(int core_id, int node_id) | 70 | static void pin_core_to_node(int core_id, int node_id) |
72 | { | 71 | { |
73 | if (cores_to_node_id[core_id] == NODE_ID_FREE) { | 72 | if (emu_cores->to_node_id[core_id] == NODE_ID_FREE) { |
74 | cores_per_node[node_id]++; | 73 | emu_cores->per_node[node_id]++; |
75 | cores_to_node_id[core_id] = node_id; | 74 | emu_cores->to_node_id[core_id] = node_id; |
76 | cores_total++; | 75 | emu_cores->total++; |
77 | } else { | 76 | } else { |
78 | WARN_ON(cores_to_node_id[core_id] != node_id); | 77 | WARN_ON(emu_cores->to_node_id[core_id] != node_id); |
79 | } | 78 | } |
80 | } | 79 | } |
81 | 80 | ||
@@ -84,7 +83,7 @@ static void pin_core_to_node(int core_id, int node_id) | |||
84 | */ | 83 | */ |
85 | static int cores_pinned(struct toptree *node) | 84 | static int cores_pinned(struct toptree *node) |
86 | { | 85 | { |
87 | return cores_per_node[node->id]; | 86 | return emu_cores->per_node[node->id]; |
88 | } | 87 | } |
89 | 88 | ||
90 | /* | 89 | /* |
@@ -92,7 +91,7 @@ static int cores_pinned(struct toptree *node) | |||
92 | */ | 91 | */ |
93 | static int core_pinned_to_node_id(struct toptree *core) | 92 | static int core_pinned_to_node_id(struct toptree *core) |
94 | { | 93 | { |
95 | return cores_to_node_id[core->id]; | 94 | return emu_cores->to_node_id[core->id]; |
96 | } | 95 | } |
97 | 96 | ||
98 | /* | 97 | /* |
@@ -174,14 +173,15 @@ static void toptree_unify_tree(struct toptree *tree) | |||
174 | 173 | ||
175 | /* | 174 | /* |
176 | * Find the best/nearest node for a given core and ensure that no node | 175 | * Find the best/nearest node for a given core and ensure that no node |
177 | * gets more than "cores_per_node_target + extra" cores. | 176 | * gets more than "emu_cores->per_node_target + extra" cores. |
178 | */ | 177 | */ |
179 | static struct toptree *node_for_core(struct toptree *numa, struct toptree *core, | 178 | static struct toptree *node_for_core(struct toptree *numa, struct toptree *core, |
180 | int extra) | 179 | int extra) |
181 | { | 180 | { |
182 | struct toptree *node, *node_best = NULL; | 181 | struct toptree *node, *node_best = NULL; |
183 | int dist_cur, dist_best; | 182 | int dist_cur, dist_best, cores_target; |
184 | 183 | ||
184 | cores_target = emu_cores->per_node_target + extra; | ||
185 | dist_best = DIST_MAX; | 185 | dist_best = DIST_MAX; |
186 | node_best = NULL; | 186 | node_best = NULL; |
187 | toptree_for_each(node, numa, NODE) { | 187 | toptree_for_each(node, numa, NODE) { |
@@ -191,7 +191,7 @@ static struct toptree *node_for_core(struct toptree *numa, struct toptree *core, | |||
191 | break; | 191 | break; |
192 | } | 192 | } |
193 | /* Skip nodes that already have enough cores */ | 193 | /* Skip nodes that already have enough cores */ |
194 | if (cores_pinned(node) >= cores_per_node_target + extra) | 194 | if (cores_pinned(node) >= cores_target) |
195 | continue; | 195 | continue; |
196 | dist_cur = dist_node_to_core(node, core); | 196 | dist_cur = dist_node_to_core(node, core); |
197 | if (dist_cur < dist_best) { | 197 | if (dist_cur < dist_best) { |
@@ -225,11 +225,11 @@ static void toptree_to_numa_single(struct toptree *numa, struct toptree *phys, | |||
225 | static void move_level_to_numa_node(struct toptree *node, struct toptree *phys, | 225 | static void move_level_to_numa_node(struct toptree *node, struct toptree *phys, |
226 | enum toptree_level level, bool perfect) | 226 | enum toptree_level level, bool perfect) |
227 | { | 227 | { |
228 | int cores_free, cores_target = emu_cores->per_node_target; | ||
228 | struct toptree *cur, *tmp; | 229 | struct toptree *cur, *tmp; |
229 | int cores_free; | ||
230 | 230 | ||
231 | toptree_for_each_safe(cur, tmp, phys, level) { | 231 | toptree_for_each_safe(cur, tmp, phys, level) { |
232 | cores_free = cores_per_node_target - toptree_count(node, CORE); | 232 | cores_free = cores_target - toptree_count(node, CORE); |
233 | if (perfect) { | 233 | if (perfect) { |
234 | if (cores_free == toptree_count(cur, CORE)) | 234 | if (cores_free == toptree_count(cur, CORE)) |
235 | toptree_move(cur, node); | 235 | toptree_move(cur, node); |
@@ -292,6 +292,20 @@ fail: | |||
292 | } | 292 | } |
293 | 293 | ||
294 | /* | 294 | /* |
295 | * Allocate and initialize core to node mapping | ||
296 | */ | ||
297 | static void create_core_to_node_map(void) | ||
298 | { | ||
299 | int i; | ||
300 | |||
301 | emu_cores = kzalloc(sizeof(*emu_cores), GFP_KERNEL); | ||
302 | if (emu_cores == NULL) | ||
303 | panic("Could not allocate cores to node memory"); | ||
304 | for (i = 0; i < ARRAY_SIZE(emu_cores->to_node_id); i++) | ||
305 | emu_cores->to_node_id[i] = NODE_ID_FREE; | ||
306 | } | ||
307 | |||
308 | /* | ||
295 | * Move cores from physical topology into NUMA target topology | 309 | * Move cores from physical topology into NUMA target topology |
296 | * and try to keep as much of the physical topology as possible. | 310 | * and try to keep as much of the physical topology as possible. |
297 | */ | 311 | */ |
@@ -299,8 +313,10 @@ static struct toptree *toptree_to_numa(struct toptree *phys) | |||
299 | { | 313 | { |
300 | static int first = 1; | 314 | static int first = 1; |
301 | struct toptree *numa; | 315 | struct toptree *numa; |
316 | int cores_total; | ||
302 | 317 | ||
303 | cores_per_node_target = (cores_total + cores_free(phys)) / emu_nodes; | 318 | cores_total = emu_cores->total + cores_free(phys); |
319 | emu_cores->per_node_target = cores_total / emu_nodes; | ||
304 | numa = toptree_new(TOPTREE_ID_NUMA, emu_nodes); | 320 | numa = toptree_new(TOPTREE_ID_NUMA, emu_nodes); |
305 | if (first) { | 321 | if (first) { |
306 | toptree_to_numa_first(numa, phys); | 322 | toptree_to_numa_first(numa, phys); |
@@ -386,8 +402,8 @@ static void print_node_to_core_map(void) | |||
386 | printk(KERN_DEBUG "NUMA node to core mapping\n"); | 402 | printk(KERN_DEBUG "NUMA node to core mapping\n"); |
387 | for (nid = 0; nid < emu_nodes; nid++) { | 403 | for (nid = 0; nid < emu_nodes; nid++) { |
388 | printk(KERN_DEBUG " node %3d: ", nid); | 404 | printk(KERN_DEBUG " node %3d: ", nid); |
389 | for (cid = 0; cid < ARRAY_SIZE(cores_to_node_id); cid++) { | 405 | for (cid = 0; cid < ARRAY_SIZE(emu_cores->to_node_id); cid++) { |
390 | if (cores_to_node_id[cid] == nid) | 406 | if (emu_cores->to_node_id[cid] == nid) |
391 | printk(KERN_CONT "%d ", cid); | 407 | printk(KERN_CONT "%d ", cid); |
392 | } | 408 | } |
393 | printk(KERN_CONT "\n"); | 409 | printk(KERN_CONT "\n"); |
@@ -404,6 +420,8 @@ static void emu_update_cpu_topology(void) | |||
404 | { | 420 | { |
405 | struct toptree *phys, *numa; | 421 | struct toptree *phys, *numa; |
406 | 422 | ||
423 | if (emu_cores == NULL) | ||
424 | create_core_to_node_map(); | ||
407 | phys = toptree_from_topology(); | 425 | phys = toptree_from_topology(); |
408 | numa = toptree_to_numa(phys); | 426 | numa = toptree_to_numa(phys); |
409 | toptree_free(phys); | 427 | toptree_free(phys); |
@@ -443,12 +461,8 @@ static int emu_setup_nodes_adjust(int nodes) | |||
443 | */ | 461 | */ |
444 | static void emu_setup(void) | 462 | static void emu_setup(void) |
445 | { | 463 | { |
446 | int i; | ||
447 | |||
448 | emu_size = emu_setup_size_adjust(emu_size); | 464 | emu_size = emu_setup_size_adjust(emu_size); |
449 | emu_nodes = emu_setup_nodes_adjust(emu_nodes); | 465 | emu_nodes = emu_setup_nodes_adjust(emu_nodes); |
450 | for (i = 0; i < ARRAY_SIZE(cores_to_node_id); i++) | ||
451 | cores_to_node_id[i] = NODE_ID_FREE; | ||
452 | pr_info("Creating %d nodes with memory stripe size %ld MB\n", | 466 | pr_info("Creating %d nodes with memory stripe size %ld MB\n", |
453 | emu_nodes, emu_size >> 20); | 467 | emu_nodes, emu_size >> 20); |
454 | } | 468 | } |