OSDN Git Service

Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages
authorVitaly Kuznetsov <vkuznets@redhat.com>
Fri, 26 Feb 2016 23:13:15 +0000 (15:13 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 2 Mar 2016 00:57:20 +0000 (16:57 -0800)
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>
drivers/hv/vmbus_drv.c

index 063e5f5..30ea8ad 100644 (file)
@@ -740,51 +740,49 @@ static void vmbus_on_msg_dpc(unsigned long data)
        struct vmbus_channel_message_table_entry *entry;
        struct onmessage_work_context *ctx;
 
-       while (1) {
-               if (msg->header.message_type == HVMSG_NONE)
-                       /* no msg */
-                       break;
+       if (msg->header.message_type == HVMSG_NONE)
+               /* no msg */
+               return;
 
-               hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+       hdr = (struct vmbus_channel_message_header *)msg->u.payload;
 
-               if (hdr->msgtype >= CHANNELMSG_COUNT) {
-                       WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
-                       goto msg_handled;
-               }
+       if (hdr->msgtype >= CHANNELMSG_COUNT) {
+               WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
+               goto msg_handled;
+       }
 
-               entry = &channel_message_table[hdr->msgtype];
-               if (entry->handler_type == VMHT_BLOCKING) {
-                       ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
-                       if (ctx == NULL)
-                               continue;
+       entry = &channel_message_table[hdr->msgtype];
+       if (entry->handler_type == VMHT_BLOCKING) {
+               ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+               if (ctx == NULL)
+                       return;
 
-                       INIT_WORK(&ctx->work, vmbus_onmessage_work);
-                       memcpy(&ctx->msg, msg, sizeof(*msg));
+               INIT_WORK(&ctx->work, vmbus_onmessage_work);
+               memcpy(&ctx->msg, msg, sizeof(*msg));
 
-                       queue_work(vmbus_connection.work_queue, &ctx->work);
-               } else
-                       entry->message_handler(hdr);
+               queue_work(vmbus_connection.work_queue, &ctx->work);
+       } else
+               entry->message_handler(hdr);
 
 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
-                * 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
+                * This will cause message queue rescan to
+                * possibly deliver another msg from the
+                * hypervisor
                 */
-               mb();
-
-               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);
-               }
+               wrmsrl(HV_X64_MSR_EOM, 0);
        }
 }