Commit 7be3e169 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Greg Kroah-Hartman

Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages

We must handle HVMSG_TIMER_EXPIRED messages in the interrupt context
and we offload all the rest to vmbus_on_msg_dpc() tasklet. This functions
loops to see if there are new messages pending. In case we'll ever see
HVMSG_TIMER_EXPIRED message there we're going to lose it as we can't
handle it from there. Avoid looping in vmbus_on_msg_dpc(), we're OK
with handling one message per interrupt.
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bec3c11b
...@@ -740,51 +740,49 @@ static void vmbus_on_msg_dpc(unsigned long data) ...@@ -740,51 +740,49 @@ static void vmbus_on_msg_dpc(unsigned long data)
struct vmbus_channel_message_table_entry *entry; struct vmbus_channel_message_table_entry *entry;
struct onmessage_work_context *ctx; struct onmessage_work_context *ctx;
while (1) { if (msg->header.message_type == HVMSG_NONE)
if (msg->header.message_type == HVMSG_NONE) /* no msg */
/* no msg */ return;
break;
hdr = (struct vmbus_channel_message_header *)msg->u.payload; hdr = (struct vmbus_channel_message_header *)msg->u.payload;
if (hdr->msgtype >= CHANNELMSG_COUNT) { if (hdr->msgtype >= CHANNELMSG_COUNT) {
WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
goto msg_handled; goto msg_handled;
} }
entry = &channel_message_table[hdr->msgtype]; entry = &channel_message_table[hdr->msgtype];
if (entry->handler_type == VMHT_BLOCKING) { if (entry->handler_type == VMHT_BLOCKING) {
ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
if (ctx == NULL) if (ctx == NULL)
continue; return;
INIT_WORK(&ctx->work, vmbus_onmessage_work); INIT_WORK(&ctx->work, vmbus_onmessage_work);
memcpy(&ctx->msg, msg, sizeof(*msg)); memcpy(&ctx->msg, msg, sizeof(*msg));
queue_work(vmbus_connection.work_queue, &ctx->work); queue_work(vmbus_connection.work_queue, &ctx->work);
} else } else
entry->message_handler(hdr); entry->message_handler(hdr);
msg_handled: msg_handled:
msg->header.message_type = HVMSG_NONE; msg->header.message_type = HVMSG_NONE;
/*
* Make sure the write to MessageType (ie set to
* HVMSG_NONE) happens before we read the
* MessagePending and EOMing. Otherwise, the EOMing
* will not deliver any more messages since there is
* no empty slot
*/
mb();
if (msg->header.message_flags.msg_pending) {
/* /*
* Make sure the write to MessageType (ie set to * This will cause message queue rescan to
* HVMSG_NONE) happens before we read the * possibly deliver another msg from the
* MessagePending and EOMing. Otherwise, the EOMing * hypervisor
* will not deliver any more messages since there is
* no empty slot
*/ */
mb(); wrmsrl(HV_X64_MSR_EOM, 0);
if (msg->header.message_flags.msg_pending) {
/*
* This will cause message queue rescan to
* possibly deliver another msg from the
* hypervisor
*/
wrmsrl(HV_X64_MSR_EOM, 0);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment