Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964886AbbD0RGk (ORCPT ); Mon, 27 Apr 2015 13:06:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60604 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932539AbbD0REc (ORCPT ); Mon, 27 Apr 2015 13:04:32 -0400 From: Vitaly Kuznetsov To: "K. Y. Srinivasan" Cc: Haiyang Zhang , devel@linuxdriverproject.org, linux-kernel@vger.kernel.org, Dexuan Cui Subject: [PATCH v2 6/6] Drivers: hv: vmbus: improve selection of an outgoing channel Date: Mon, 27 Apr 2015 19:04:16 +0200 Message-Id: <1430154256-26853-7-git-send-email-vkuznets@redhat.com> In-Reply-To: <1430154256-26853-1-git-send-email-vkuznets@redhat.com> References: <1430154256-26853-1-git-send-email-vkuznets@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3380 Lines: 100 vmbus_get_outgoing_channel() implements the following algorithm for selecting an outgoing channel (despite the comment before the function saying it distributes the load equally): 1) If we have no subchannels return the primary channel; 2) If primary->next_oc is grater than primary->num_sc reset the primary->next_oc to 0 and return the primary channel; 3) Aim for the primary->next_oc subchannel, increment primary->next_oc; 4) Loop through all opened subchannels. If we see a channel which has target_cpu == current_cpu return it. If we reached the primary->next_oc'th open subchannel return it; 5) Return the primary channel. The implementation also skips the subchannel No. 0 unless it matches the current cpu as we assign i to 1 in the initialization. Improve the algorithm to do the full scan searching for a (sub)channel with the target_cpu == current_cpu, use round-robin as a fallback. Signed-off-by: Vitaly Kuznetsov --- drivers/hv/channel_mgmt.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 1f1417d..cdc3914 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -823,46 +823,45 @@ cleanup: } /* - * Retrieve the (sub) channel on which to send an outgoing request. - * When a primary channel has multiple sub-channels, we try to - * distribute the load equally amongst all available channels. + * Retrieve the (sub) channel on which to send an outgoing request. When a + * primary channel has multiple sub-channels, we try to find a (sub)channel + * with target_cpu == current CPU and we try to distribute the load equally + * amongst all available channels when we fail. */ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) { struct list_head *cur, *tmp; - int cur_cpu; struct vmbus_channel *cur_channel; - struct vmbus_channel *outgoing_channel = primary; - int next_channel; - int i = 1; + struct vmbus_channel *out_channel_rr = NULL; + int i = 0; if (list_empty(&primary->sc_list)) - return outgoing_channel; + return primary; - next_channel = primary->next_oc++; - - if (next_channel > (primary->num_sc)) { + if (primary->next_oc >= primary->num_sc) { primary->next_oc = 0; - return outgoing_channel; + return primary; } - cur_cpu = hv_context.vp_index[get_cpu()]; - put_cpu(); + if (primary->target_cpu == smp_processor_id()) + return primary; + list_for_each_safe(cur, tmp, &primary->sc_list) { + i++; cur_channel = list_entry(cur, struct vmbus_channel, sc_list); if (cur_channel->state != CHANNEL_OPENED_STATE) continue; - if (cur_channel->target_vp == cur_cpu) + if (cur_channel->target_cpu == smp_processor_id()) return cur_channel; - if (i == next_channel) - return cur_channel; - - i++; + if (!out_channel_rr && i > primary->next_oc) { + primary->next_oc = i; + out_channel_rr = cur_channel; + } } - return outgoing_channel; + return out_channel_rr ? out_channel_rr : primary; } EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel); -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/