summaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2016-02-26 18:13:15 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-03-01 19:57:20 -0500
commit7be3e169444d2c625f15a0b6639252b98d1f226a (patch)
treec26bf9fe6a7f9ccbd28fa41177cb35533827569c /drivers/hv
parentbec3c11bad0e7ac05fb90f204d0ab6f79945822b (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.c68
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
768msg_handled: 767msg_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