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: Vitaly Kuznetsov <vkuznets@redhat.com> Reviewed-by: Radim Kr.má<rkrcmar@redhat.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
bec3c11bad
commit
7be3e16944
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user