From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161621AbcA1ExZ (ORCPT ); Wed, 27 Jan 2016 23:53:25 -0500 Received: from p3plsmtps2ded03.prod.phx3.secureserver.net ([208.109.80.60]:47765 "EHLO p3plsmtps2ded03.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161560AbcA1ExU (ORCPT ); Wed, 27 Jan 2016 23:53:20 -0500 x-originating-ip: 72.167.245.219 From: "K. Y. Srinivasan" To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, vkuznets@redhat.com, jasowang@redhat.com Cc: "K. Y. Srinivasan" Subject: [PATCH V2 03/13] Drivers: hv: vmbus: avoid scheduling in interrupt context in vmbus_initiate_unload() Date: Wed, 27 Jan 2016 22:29:35 -0800 Message-Id: <1453962585-32069-3-git-send-email-kys@microsoft.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1453962585-32069-1-git-send-email-kys@microsoft.com> References: <1453962559-32028-1-git-send-email-kys@microsoft.com> <1453962585-32069-1-git-send-email-kys@microsoft.com> X-CMAE-Envelope: MS4wfK31du4Hx6Kc/rJY+3vvGGkL3ACPwcG0zWDQeY3c20Cx6OBFqxy4TWdfYy7eIlO2P8ut8TnFfXoiKI4ijVBNqZ1WWIMpSGGxxuDlVbZgokNq/3ND4wy8 yKLH1VXoMvx7z4nElxpCaWTYwj3p5OVxeyotz/5ewch7mBuldz/8fDUnRNCjn8Jiw11aMHVJydTp1E4LYXrVwBhfYcnegXOiijr4QXDUQM3BK/g3uwRjp91a K8liVxy3JafArHrdFjfn1NcIDGOv1ofJdQpbLZvNZ8o9WL9tufMdJSf0x65SOAD/F0I72wJ45zwAuJha3kGyYhd1hSe7v1lU4vZ39T/on4H9cnpGCt/Nc/Jm kmN0XnkzEHNUMT0eafQUl3jQl491LgxS83bf4e3su06twoThtW7IUZmIP6tvOOpAPGYLLgtx Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Vitaly Kuznetsov We have to call vmbus_initiate_unload() on crash to make kdump work but the crash can also be happening in interrupt (e.g. Sysrq + c results in such) where we can't schedule or the following will happen: [ 314.905786] bad: scheduling from the idle thread! Just skipping the wait (and even adding some random wait here) won't help: to make host-side magic working we're supposed to receive CHANNELMSG_UNLOAD (and actually confirm the fact that we received it) but we can't use interrupt-base path (vmbus_isr()-> vmbus_on_msg_dpc()). Implement a simple busy wait ignoring all the other messages and use it if we're in an interrupt context. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 1 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index af1d82e..d6c6114 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "hyperv_vmbus.h" @@ -589,6 +590,40 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) channel->target_vp = hv_context.vp_index[cur_cpu]; } +static void vmbus_wait_for_unload(void) +{ + int cpu = smp_processor_id(); + void *page_addr = hv_context.synic_message_page[cpu]; + struct hv_message *msg = (struct hv_message *)page_addr + + VMBUS_MESSAGE_SINT; + struct vmbus_channel_message_header *hdr; + bool unloaded = false; + + while (1) { + if (msg->header.message_type == HVMSG_NONE) { + mdelay(10); + continue; + } + + hdr = (struct vmbus_channel_message_header *)msg->u.payload; + if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE) + unloaded = true; + + msg->header.message_type = HVMSG_NONE; + /* + * header.message_type needs to be written before we do + * wrmsrl() below. + */ + mb(); + + if (msg->header.message_flags.msg_pending) + wrmsrl(HV_X64_MSR_EOM, 0); + + if (unloaded) + break; + } +} + /* * vmbus_unload_response - Handler for the unload response. */ @@ -614,7 +649,14 @@ void vmbus_initiate_unload(void) hdr.msgtype = CHANNELMSG_UNLOAD; vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header)); - wait_for_completion(&vmbus_connection.unload_event); + /* + * vmbus_initiate_unload() is also called on crash and the crash can be + * happening in an interrupt context, where scheduling is impossible. + */ + if (!in_interrupt()) + wait_for_completion(&vmbus_connection.unload_event); + else + vmbus_wait_for_unload(); } /* -- 1.7.4.1