aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/channel_mgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/channel_mgmt.c')
-rw-r--r--drivers/hv/channel_mgmt.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 38b682bab85a..b6c1211b4df7 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -597,27 +597,55 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
597 597
598static void vmbus_wait_for_unload(void) 598static void vmbus_wait_for_unload(void)
599{ 599{
600 int cpu = smp_processor_id(); 600 int cpu;
601 void *page_addr = hv_context.synic_message_page[cpu]; 601 void *page_addr;
602 struct hv_message *msg = (struct hv_message *)page_addr + 602 struct hv_message *msg;
603 VMBUS_MESSAGE_SINT;
604 struct vmbus_channel_message_header *hdr; 603 struct vmbus_channel_message_header *hdr;
605 bool unloaded = false; 604 u32 message_type;
606 605
606 /*
607 * CHANNELMSG_UNLOAD_RESPONSE is always delivered to the CPU which was
608 * used for initial contact or to CPU0 depending on host version. When
609 * we're crashing on a different CPU let's hope that IRQ handler on
610 * the cpu which receives CHANNELMSG_UNLOAD_RESPONSE is still
611 * functional and vmbus_unload_response() will complete
612 * vmbus_connection.unload_event. If not, the last thing we can do is
613 * read message pages for all CPUs directly.
614 */
607 while (1) { 615 while (1) {
608 if (READ_ONCE(msg->header.message_type) == HVMSG_NONE) { 616 if (completion_done(&vmbus_connection.unload_event))
609 mdelay(10); 617 break;
610 continue;
611 }
612 618
613 hdr = (struct vmbus_channel_message_header *)msg->u.payload; 619 for_each_online_cpu(cpu) {
614 if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE) 620 page_addr = hv_context.synic_message_page[cpu];
615 unloaded = true; 621 msg = (struct hv_message *)page_addr +
622 VMBUS_MESSAGE_SINT;
616 623
617 vmbus_signal_eom(msg); 624 message_type = READ_ONCE(msg->header.message_type);
625 if (message_type == HVMSG_NONE)
626 continue;
618 627
619 if (unloaded) 628 hdr = (struct vmbus_channel_message_header *)
620 break; 629 msg->u.payload;
630
631 if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
632 complete(&vmbus_connection.unload_event);
633
634 vmbus_signal_eom(msg, message_type);
635 }
636
637 mdelay(10);
638 }
639
640 /*
641 * We're crashing and already got the UNLOAD_RESPONSE, cleanup all
642 * maybe-pending messages on all CPUs to be able to receive new
643 * messages after we reconnect.
644 */
645 for_each_online_cpu(cpu) {
646 page_addr = hv_context.synic_message_page[cpu];
647 msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
648 msg->header.message_type = HVMSG_NONE;
621 } 649 }
622} 650}
623 651