Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Drivers: hv: vmbus: Implement the protocol for tearing down vmbus state

Implement the protocol for tearing down the monitor state established with
the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Tested-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

K. Y. Srinivasan and committed by
Greg Kroah-Hartman
2db84eff db9ba208

+34 -1
+25
drivers/hv/channel_mgmt.c
··· 422 422 } 423 423 424 424 /* 425 + * vmbus_unload_response - Handler for the unload response. 426 + */ 427 + static void vmbus_unload_response(struct vmbus_channel_message_header *hdr) 428 + { 429 + /* 430 + * This is a global event; just wakeup the waiting thread. 431 + * Once we successfully unload, we can cleanup the monitor state. 432 + */ 433 + complete(&vmbus_connection.unload_event); 434 + } 435 + 436 + void vmbus_initiate_unload(void) 437 + { 438 + struct vmbus_channel_message_header hdr; 439 + 440 + init_completion(&vmbus_connection.unload_event); 441 + memset(&hdr, 0, sizeof(struct vmbus_channel_message_header)); 442 + hdr.msgtype = CHANNELMSG_UNLOAD; 443 + vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header)); 444 + 445 + wait_for_completion(&vmbus_connection.unload_event); 446 + } 447 + 448 + /* 425 449 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. 426 450 * 427 451 */ ··· 741 717 {CHANNELMSG_INITIATE_CONTACT, 0, NULL}, 742 718 {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response}, 743 719 {CHANNELMSG_UNLOAD, 0, NULL}, 720 + {CHANNELMSG_UNLOAD_RESPONSE, 1, vmbus_unload_response}, 744 721 }; 745 722 746 723 /*
+5
drivers/hv/connection.c
··· 227 227 228 228 void vmbus_disconnect(void) 229 229 { 230 + /* 231 + * First send the unload request to the host. 232 + */ 233 + vmbus_initiate_unload(); 234 + 230 235 if (vmbus_connection.work_queue) { 231 236 drain_workqueue(vmbus_connection.work_queue); 232 237 destroy_workqueue(vmbus_connection.work_queue);
+2
drivers/hv/hyperv_vmbus.h
··· 647 647 648 648 atomic_t next_gpadl_handle; 649 649 650 + struct completion unload_event; 650 651 /* 651 652 * Represents channel interrupts. Each bit position represents a 652 653 * channel. When a channel sends an interrupt via VMBUS, it finds its ··· 742 741 int hv_fcopy_init(struct hv_util_service *); 743 742 void hv_fcopy_deinit(void); 744 743 void hv_fcopy_onchannelcallback(void *); 744 + void vmbus_initiate_unload(void); 745 745 746 746 static inline void hv_poll_channel(struct vmbus_channel *channel, 747 747 void (*cb)(void *))
+1 -1
drivers/hv/vmbus_drv.c
··· 1106 1106 1107 1107 vmbus_connection.conn_state = DISCONNECTED; 1108 1108 hv_synic_clockevents_cleanup(); 1109 + vmbus_disconnect(); 1109 1110 hv_remove_vmbus_irq(); 1110 1111 vmbus_free_channels(); 1111 1112 if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { ··· 1119 1118 smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1); 1120 1119 acpi_bus_unregister_driver(&vmbus_acpi_driver); 1121 1120 hv_cpu_hotplug_quirk(false); 1122 - vmbus_disconnect(); 1123 1121 } 1124 1122 1125 1123
+1
include/linux/hyperv.h
··· 389 389 CHANNELMSG_INITIATE_CONTACT = 14, 390 390 CHANNELMSG_VERSION_RESPONSE = 15, 391 391 CHANNELMSG_UNLOAD = 16, 392 + CHANNELMSG_UNLOAD_RESPONSE = 17, 392 393 CHANNELMSG_COUNT 393 394 }; 394 395