diff options
-rw-r--r-- | drivers/hv/channel_mgmt.c | 30 | ||||
-rw-r--r-- | include/linux/hyperv.h | 3 |
2 files changed, 18 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) | |||
350 | } | 350 | } |
351 | 351 | ||
352 | newchannel->state = CHANNEL_OPEN_STATE; | 352 | newchannel->state = CHANNEL_OPEN_STATE; |
353 | channel->num_sc++; | ||
353 | if (channel->sc_creation_callback != NULL) | 354 | if (channel->sc_creation_callback != NULL) |
354 | /* | 355 | /* |
355 | * We need to invoke the sub-channel creation | 356 | * We need to invoke the sub-channel creation |
@@ -862,9 +863,8 @@ cleanup: | |||
862 | 863 | ||
863 | /* | 864 | /* |
864 | * Retrieve the (sub) channel on which to send an outgoing request. | 865 | * Retrieve the (sub) channel on which to send an outgoing request. |
865 | * When a primary channel has multiple sub-channels, we choose a | 866 | * When a primary channel has multiple sub-channels, we try to |
866 | * channel whose VCPU binding is closest to the VCPU on which | 867 | * distribute the load equally amongst all available channels. |
867 | * this call is being made. | ||
868 | */ | 868 | */ |
869 | struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) | 869 | struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) |
870 | { | 870 | { |
@@ -872,11 +872,19 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) | |||
872 | int cur_cpu; | 872 | int cur_cpu; |
873 | struct vmbus_channel *cur_channel; | 873 | struct vmbus_channel *cur_channel; |
874 | struct vmbus_channel *outgoing_channel = primary; | 874 | struct vmbus_channel *outgoing_channel = primary; |
875 | int cpu_distance, new_cpu_distance; | 875 | int next_channel; |
876 | int i = 1; | ||
876 | 877 | ||
877 | if (list_empty(&primary->sc_list)) | 878 | if (list_empty(&primary->sc_list)) |
878 | return outgoing_channel; | 879 | return outgoing_channel; |
879 | 880 | ||
881 | next_channel = primary->next_oc++; | ||
882 | |||
883 | if (next_channel > (primary->num_sc)) { | ||
884 | primary->next_oc = 0; | ||
885 | return outgoing_channel; | ||
886 | } | ||
887 | |||
880 | cur_cpu = hv_context.vp_index[get_cpu()]; | 888 | cur_cpu = hv_context.vp_index[get_cpu()]; |
881 | put_cpu(); | 889 | put_cpu(); |
882 | list_for_each_safe(cur, tmp, &primary->sc_list) { | 890 | list_for_each_safe(cur, tmp, &primary->sc_list) { |
@@ -887,18 +895,10 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) | |||
887 | if (cur_channel->target_vp == cur_cpu) | 895 | if (cur_channel->target_vp == cur_cpu) |
888 | return cur_channel; | 896 | return cur_channel; |
889 | 897 | ||
890 | cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ? | 898 | if (i == next_channel) |
891 | (outgoing_channel->target_vp - cur_cpu) : | 899 | return cur_channel; |
892 | (cur_cpu - outgoing_channel->target_vp)); | ||
893 | |||
894 | new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ? | ||
895 | (cur_channel->target_vp - cur_cpu) : | ||
896 | (cur_cpu - cur_channel->target_vp)); | ||
897 | |||
898 | if (cpu_distance < new_cpu_distance) | ||
899 | continue; | ||
900 | 900 | ||
901 | outgoing_channel = cur_channel; | 901 | i++; |
902 | } | 902 | } |
903 | 903 | ||
904 | return outgoing_channel; | 904 | return outgoing_channel; |
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index dd92a854c700..1ca582457076 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -761,6 +761,9 @@ struct vmbus_channel { | |||
761 | * link up channels based on their CPU affinity. | 761 | * link up channels based on their CPU affinity. |
762 | */ | 762 | */ |
763 | struct list_head percpu_list; | 763 | struct list_head percpu_list; |
764 | |||
765 | int num_sc; | ||
766 | int next_oc; | ||
764 | }; | 767 | }; |
765 | 768 | ||
766 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) | 769 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) |