diff options
author | Vitaly Kuznetsov <vkuznets@redhat.com> | 2016-02-26 18:13:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-03-01 19:57:20 -0500 |
commit | 7be3e169444d2c625f15a0b6639252b98d1f226a (patch) | |
tree | c26bf9fe6a7f9ccbd28fa41177cb35533827569c /drivers/hv | |
parent | bec3c11bad0e7ac05fb90f204d0ab6f79945822b (diff) |
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>
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/vmbus_drv.c | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 063e5f53ca78..30ea8ad902e2 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -740,51 +740,49 @@ static void vmbus_on_msg_dpc(unsigned long data) | |||
740 | struct vmbus_channel_message_table_entry *entry; | 740 | struct vmbus_channel_message_table_entry *entry; |
741 | struct onmessage_work_context *ctx; | 741 | struct onmessage_work_context *ctx; |
742 | 742 | ||
743 | while (1) { | 743 | if (msg->header.message_type == HVMSG_NONE) |
744 | if (msg->header.message_type == HVMSG_NONE) | 744 | /* no msg */ |
745 | /* no msg */ | 745 | return; |
746 | break; | ||
747 | 746 | ||
748 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; | 747 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; |
749 | 748 | ||
750 | if (hdr->msgtype >= CHANNELMSG_COUNT) { | 749 | if (hdr->msgtype >= CHANNELMSG_COUNT) { |
751 | WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); | 750 | WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); |
752 | goto msg_handled; | 751 | goto msg_handled; |
753 | } | 752 | } |
754 | 753 | ||
755 | entry = &channel_message_table[hdr->msgtype]; | 754 | entry = &channel_message_table[hdr->msgtype]; |
756 | if (entry->handler_type == VMHT_BLOCKING) { | 755 | if (entry->handler_type == VMHT_BLOCKING) { |
757 | ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); | 756 | ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); |
758 | if (ctx == NULL) | 757 | if (ctx == NULL) |
759 | continue; | 758 | return; |
760 | 759 | ||
761 | INIT_WORK(&ctx->work, vmbus_onmessage_work); | 760 | INIT_WORK(&ctx->work, vmbus_onmessage_work); |
762 | memcpy(&ctx->msg, msg, sizeof(*msg)); | 761 | memcpy(&ctx->msg, msg, sizeof(*msg)); |
763 | 762 | ||
764 | queue_work(vmbus_connection.work_queue, &ctx->work); | 763 | queue_work(vmbus_connection.work_queue, &ctx->work); |
765 | } else | 764 | } else |
766 | entry->message_handler(hdr); | 765 | entry->message_handler(hdr); |
767 | 766 | ||
768 | msg_handled: | 767 | msg_handled: |
769 | msg->header.message_type = HVMSG_NONE; | 768 | msg->header.message_type = HVMSG_NONE; |
769 | |||
770 | /* | ||
771 | * Make sure the write to MessageType (ie set to | ||
772 | * HVMSG_NONE) happens before we read the | ||
773 | * MessagePending and EOMing. Otherwise, the EOMing | ||
774 | * will not deliver any more messages since there is | ||
775 | * no empty slot | ||
776 | */ | ||
777 | mb(); | ||
770 | 778 | ||
779 | if (msg->header.message_flags.msg_pending) { | ||
771 | /* | 780 | /* |
772 | * Make sure the write to MessageType (ie set to | 781 | * This will cause message queue rescan to |
773 | * HVMSG_NONE) happens before we read the | 782 | * possibly deliver another msg from the |
774 | * MessagePending and EOMing. Otherwise, the EOMing | 783 | * hypervisor |
775 | * will not deliver any more messages since there is | ||
776 | * no empty slot | ||
777 | */ | 784 | */ |
778 | mb(); | 785 | wrmsrl(HV_X64_MSR_EOM, 0); |
779 | |||
780 | if (msg->header.message_flags.msg_pending) { | ||
781 | /* | ||
782 | * This will cause message queue rescan to | ||
783 | * possibly deliver another msg from the | ||
784 | * hypervisor | ||
785 | */ | ||
786 | wrmsrl(HV_X64_MSR_EOM, 0); | ||
787 | } | ||
788 | } | 786 | } |
789 | } | 787 | } |
790 | 788 | ||