From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg0-f45.google.com ([74.125.83.45]:33109 "EHLO mail-pg0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754169AbdERWZa (ORCPT ); Thu, 18 May 2017 18:25:30 -0400 Received: by mail-pg0-f45.google.com with SMTP id u187so29001997pgb.0 for ; Thu, 18 May 2017 15:25:29 -0700 (PDT) From: Stephen Hemminger To: kys@microsoft.com Cc: devel@linuxdriverproject.org, stable@vger.kernel.org, Stephen Hemminger Subject: [PATCH v2] vmbus: fix missed ring events on boot Date: Thu, 18 May 2017 15:25:21 -0700 Message-Id: <20170518222521.31545-1-sthemmin@microsoft.com> Sender: stable-owner@vger.kernel.org List-ID: During initialization, the channel initialization code schedules the tasklet to scan the VMBUS receive event page (i.e. simulates an interrupt). The problem was that it invokes the tasklet on a different CPU from where it normally runs and therefore if an event is present, it will clear the bit but not find the associated channel. This can lead to missed events, typically stuck tasks, during bootup when sub channels are being initialized. Typically seen as stuck boot with 8 or more CPU's. This patch is not necessary for upstream (4.11 and later) since commit 631e63a9f346 ("vmbus: change to per channel tasklet"). This changed vmbus code to get rid of common tasklet which caused the problem. Cc: stable@vger.kernel.org Fixes: 638fea33aee8 ("Drivers: hv: vmbus: fix the race when querying & updating the percpu list") Signed-off-by: Stephen Hemminger --- v2 - fix generic in hv_event_tasklet_enable drivers/hv/channel_mgmt.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index a58cd102af1b..51be9ec8a51b 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -361,8 +361,17 @@ void hv_event_tasklet_enable(struct vmbus_channel *channel) tasklet = hv_context.event_dpc[channel->target_cpu]; tasklet_enable(tasklet); - /* In case there is any pending event */ - tasklet_schedule(tasklet); + /* + * In case there is any pending event schedule a rescan + * but must be on the correct CPU for the channel. + */ + if (channel->target_cpu == get_cpu()) + tasklet_schedule(tasklet); + else + smp_call_function_single(channel->target_cpu, + (smp_call_func_t)tasklet_schedule, + tasklet, false); + put_cpu(); } void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) -- 2.11.0