diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2015-02-28 22:39:02 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-02 06:31:47 +0300 |
commit | a13e8bbe851a96a0e78c2bd599bc34082fa697cd (patch) | |
tree | 3901b34efd778528b85afd85c36cb33829c79949 /drivers/hv | |
parent | 96c1d0581d00f7abe033350edb021a9d947d8d81 (diff) | |
download | linux-a13e8bbe851a96a0e78c2bd599bc34082fa697cd.tar.xz |
Drivers: hv: vmbus: Use a round-robin algorithm for picking the outgoing channel
The current algorithm for picking an outgoing channel was not distributing
the load well. Implement a simple round-robin scheme to ensure good
distribution of the outgoing traffic.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/channel_mgmt.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index b1e5a5fdaf7f..611789139f9b 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -350,6 +350,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) } newchannel->state = CHANNEL_OPEN_STATE; + channel->num_sc++; if (channel->sc_creation_callback != NULL) /* * We need to invoke the sub-channel creation @@ -862,9 +863,8 @@ cleanup: /* * Retrieve the (sub) channel on which to send an outgoing request. - * When a primary channel has multiple sub-channels, we choose a - * channel whose VCPU binding is closest to the VCPU on which - * this call is being made. + * When a primary channel has multiple sub-channels, we try to + * distribute the load equally amongst all available channels. */ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) { @@ -872,11 +872,19 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) int cur_cpu; struct vmbus_channel *cur_channel; struct vmbus_channel *outgoing_channel = primary; - int cpu_distance, new_cpu_distance; + int next_channel; + int i = 1; if (list_empty(&primary->sc_list)) return outgoing_channel; + next_channel = primary->next_oc++; + + if (next_channel > (primary->num_sc)) { + primary->next_oc = 0; + return outgoing_channel; + } + cur_cpu = hv_context.vp_index[get_cpu()]; put_cpu(); list_for_each_safe(cur, tmp, &primary->sc_list) { @@ -887,18 +895,10 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) if (cur_channel->target_vp == cur_cpu) return cur_channel; - cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ? - (outgoing_channel->target_vp - cur_cpu) : - (cur_cpu - outgoing_channel->target_vp)); - - new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ? - (cur_channel->target_vp - cur_cpu) : - (cur_cpu - cur_channel->target_vp)); - - if (cpu_distance < new_cpu_distance) - continue; + if (i == next_channel) + return cur_channel; - outgoing_channel = cur_channel; + i++; } return outgoing_channel; |