diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2015-08-05 03:52:38 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-08-05 14:41:31 -0400 |
commit | 9f01ec53458d9e9b68f1c555e773b5d1a1f66e94 (patch) | |
tree | ce76ed3d4a11ec2035a42a154a735363f642250f /drivers/hv | |
parent | 3546448338e76a52d4f86eb3680cb2934e22d89b (diff) |
Drivers: hv: vmbus: Improve the CPU affiliation for channels
The current code tracks the assigned CPUs within a NUMA node in the context of
the primary channel. So, if we have a VM with a single NUMA node with 8 VCPUs, we may
end up unevenly distributing the channel load. Fix the issue by tracking affiliations
globally.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/channel_mgmt.c | 11 | ||||
-rw-r--r-- | drivers/hv/hv.c | 9 | ||||
-rw-r--r-- | drivers/hv/hyperv_vmbus.h | 5 |
3 files changed, 20 insertions, 5 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 30613dfa38b3..39c5afc7970c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -392,6 +392,7 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui | |||
392 | struct vmbus_channel *primary = channel->primary_channel; | 392 | struct vmbus_channel *primary = channel->primary_channel; |
393 | int next_node; | 393 | int next_node; |
394 | struct cpumask available_mask; | 394 | struct cpumask available_mask; |
395 | struct cpumask *alloced_mask; | ||
395 | 396 | ||
396 | for (i = IDE; i < MAX_PERF_CHN; i++) { | 397 | for (i = IDE; i < MAX_PERF_CHN; i++) { |
397 | if (!memcmp(type_guid->b, hp_devs[i].guid, | 398 | if (!memcmp(type_guid->b, hp_devs[i].guid, |
@@ -409,7 +410,6 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui | |||
409 | * channel, bind it to cpu 0. | 410 | * channel, bind it to cpu 0. |
410 | */ | 411 | */ |
411 | channel->numa_node = 0; | 412 | channel->numa_node = 0; |
412 | cpumask_set_cpu(0, &channel->alloced_cpus_in_node); | ||
413 | channel->target_cpu = 0; | 413 | channel->target_cpu = 0; |
414 | channel->target_vp = hv_context.vp_index[0]; | 414 | channel->target_vp = hv_context.vp_index[0]; |
415 | return; | 415 | return; |
@@ -434,21 +434,22 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui | |||
434 | channel->numa_node = next_node; | 434 | channel->numa_node = next_node; |
435 | primary = channel; | 435 | primary = channel; |
436 | } | 436 | } |
437 | alloced_mask = &hv_context.hv_numa_map[primary->numa_node]; | ||
437 | 438 | ||
438 | if (cpumask_weight(&primary->alloced_cpus_in_node) == | 439 | if (cpumask_weight(alloced_mask) == |
439 | cpumask_weight(cpumask_of_node(primary->numa_node))) { | 440 | cpumask_weight(cpumask_of_node(primary->numa_node))) { |
440 | /* | 441 | /* |
441 | * We have cycled through all the CPUs in the node; | 442 | * We have cycled through all the CPUs in the node; |
442 | * reset the alloced map. | 443 | * reset the alloced map. |
443 | */ | 444 | */ |
444 | cpumask_clear(&primary->alloced_cpus_in_node); | 445 | cpumask_clear(alloced_mask); |
445 | } | 446 | } |
446 | 447 | ||
447 | cpumask_xor(&available_mask, &primary->alloced_cpus_in_node, | 448 | cpumask_xor(&available_mask, alloced_mask, |
448 | cpumask_of_node(primary->numa_node)); | 449 | cpumask_of_node(primary->numa_node)); |
449 | 450 | ||
450 | cur_cpu = cpumask_next(-1, &available_mask); | 451 | cur_cpu = cpumask_next(-1, &available_mask); |
451 | cpumask_set_cpu(cur_cpu, &primary->alloced_cpus_in_node); | 452 | cpumask_set_cpu(cur_cpu, alloced_mask); |
452 | 453 | ||
453 | channel->target_cpu = cur_cpu; | 454 | channel->target_cpu = cur_cpu; |
454 | channel->target_vp = hv_context.vp_index[cur_cpu]; | 455 | channel->target_vp = hv_context.vp_index[cur_cpu]; |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 41d8072d61d9..fd93cfde96d0 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -332,6 +332,13 @@ int hv_synic_alloc(void) | |||
332 | size_t ced_size = sizeof(struct clock_event_device); | 332 | size_t ced_size = sizeof(struct clock_event_device); |
333 | int cpu; | 333 | int cpu; |
334 | 334 | ||
335 | hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids, | ||
336 | GFP_ATOMIC); | ||
337 | if (hv_context.hv_numa_map == NULL) { | ||
338 | pr_err("Unable to allocate NUMA map\n"); | ||
339 | goto err; | ||
340 | } | ||
341 | |||
335 | for_each_online_cpu(cpu) { | 342 | for_each_online_cpu(cpu) { |
336 | hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC); | 343 | hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC); |
337 | if (hv_context.event_dpc[cpu] == NULL) { | 344 | if (hv_context.event_dpc[cpu] == NULL) { |
@@ -345,6 +352,7 @@ int hv_synic_alloc(void) | |||
345 | pr_err("Unable to allocate clock event device\n"); | 352 | pr_err("Unable to allocate clock event device\n"); |
346 | goto err; | 353 | goto err; |
347 | } | 354 | } |
355 | |||
348 | hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu); | 356 | hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu); |
349 | 357 | ||
350 | hv_context.synic_message_page[cpu] = | 358 | hv_context.synic_message_page[cpu] = |
@@ -393,6 +401,7 @@ void hv_synic_free(void) | |||
393 | { | 401 | { |
394 | int cpu; | 402 | int cpu; |
395 | 403 | ||
404 | kfree(hv_context.hv_numa_map); | ||
396 | for_each_online_cpu(cpu) | 405 | for_each_online_cpu(cpu) |
397 | hv_synic_free_cpu(cpu); | 406 | hv_synic_free_cpu(cpu); |
398 | } | 407 | } |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 638370701657..6f258255ac94 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -551,6 +551,11 @@ struct hv_context { | |||
551 | * Support PV clockevent device. | 551 | * Support PV clockevent device. |
552 | */ | 552 | */ |
553 | struct clock_event_device *clk_evt[NR_CPUS]; | 553 | struct clock_event_device *clk_evt[NR_CPUS]; |
554 | /* | ||
555 | * To manage allocations in a NUMA node. | ||
556 | * Array indexed by numa node ID. | ||
557 | */ | ||
558 | struct cpumask *hv_numa_map; | ||
554 | }; | 559 | }; |
555 | 560 | ||
556 | extern struct hv_context hv_context; | 561 | extern struct hv_context hv_context; |