Patch "[PATCH 098/135] Drivers: hv: vmbus: avoid scheduling in interrupt" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
[PATCH 098/135] Drivers: hv: vmbus: avoid scheduling in interrupt
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
0098-Drivers-hv-vmbus-avoid-scheduling-in-interrupt-conte.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
04023b914cfb9c54dc70f1407086536218145729Mon Sep 17 00:00:00 2001
From: Vitaly Kuznetsov <[email protected]>
Date: Wed, 27 Jan 2016 22:29:35 -0800
Subject: [PATCH 098/135] Drivers: hv: vmbus: avoid scheduling in interrupt
context in vmbus_initiate_unload()
[ Upstream commit 415719160de3fae3bb9cbc617664649919cd00d0 ]
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.
--- drivers/hv/channel_mgmt.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-)
drivers/hv/channel_mgmt.c +43 -1
@@ -28,6 +28,7 @@#include <linux/list.h> #include <linux/module.h> #include <linux/completion.h> +#include <linux/delay.h> #include <linux/hyperv.h> #include "hyperv_vmbus.h"
@@ -499,6 +500,40 @@ static void init_vp_index(struct vmbus_c 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. */
@@ -524,7 +559,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 (); }/*
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/0038-drivers-hv-cleanup-synic-msrs-if-vmbus-connect-faile.patch queue-4.4/0097-Drivers-hv-vmbus-avoid-infinite-loop-in-init_vp_inde.patch queue-4.4/0118-clocksource-Allow-unregistering-the-watchdog.patch queue-4.4/0099-Drivers-hv-vmbus-don-t-manipulate-with-clocksources-.patch queue-4.4/0127-x86-hyperv-Avoid-reporting-bogus-NMI-status-for-Gen2.patch queue-4.4/0098-Drivers-hv-vmbus-avoid-scheduling-in-interrupt-conte.patch