aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2015-04-23 00:31:32 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-24 15:18:24 -0400
commit2db84eff127e3f4b3635edc589cd6a56db8755a3 (patch)
tree2890e6494ebeb52bfdbaa182a9e58d3f2734d57e /drivers/hv
parentdb9ba2088f6507fee370904f02db1eb9b49bd088 (diff)
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>
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/channel_mgmt.c25
-rw-r--r--drivers/hv/connection.c5
-rw-r--r--drivers/hv/hyperv_vmbus.h2
-rw-r--r--drivers/hv/vmbus_drv.c2
4 files changed, 33 insertions, 1 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 865a3afa1d86..4b9d89ab44d3 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -422,6 +422,30 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
422} 422}
423 423
424/* 424/*
425 * vmbus_unload_response - Handler for the unload response.
426 */
427static 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
436void 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 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. 449 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
426 * 450 *
427 */ 451 */
@@ -717,6 +741,7 @@ struct vmbus_channel_message_table_entry
717 {CHANNELMSG_INITIATE_CONTACT, 0, NULL}, 741 {CHANNELMSG_INITIATE_CONTACT, 0, NULL},
718 {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response}, 742 {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response},
719 {CHANNELMSG_UNLOAD, 0, NULL}, 743 {CHANNELMSG_UNLOAD, 0, NULL},
744 {CHANNELMSG_UNLOAD_RESPONSE, 1, vmbus_unload_response},
720}; 745};
721 746
722/* 747/*
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index b27220a425f4..acd50e9d666a 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -227,6 +227,11 @@ cleanup:
227 227
228void vmbus_disconnect(void) 228void vmbus_disconnect(void)
229{ 229{
230 /*
231 * First send the unload request to the host.
232 */
233 vmbus_initiate_unload();
234
230 if (vmbus_connection.work_queue) { 235 if (vmbus_connection.work_queue) {
231 drain_workqueue(vmbus_connection.work_queue); 236 drain_workqueue(vmbus_connection.work_queue);
232 destroy_workqueue(vmbus_connection.work_queue); 237 destroy_workqueue(vmbus_connection.work_queue);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 138d6634c79d..cddc0c9f6bf9 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -647,6 +647,7 @@ struct vmbus_connection {
647 647
648 atomic_t next_gpadl_handle; 648 atomic_t next_gpadl_handle;
649 649
650 struct completion unload_event;
650 /* 651 /*
651 * Represents channel interrupts. Each bit position represents a 652 * Represents channel interrupts. Each bit position represents a
652 * channel. When a channel sends an interrupt via VMBUS, it finds its 653 * channel. When a channel sends an interrupt via VMBUS, it finds its
@@ -741,6 +742,7 @@ void hv_vss_onchannelcallback(void *);
741int hv_fcopy_init(struct hv_util_service *); 742int hv_fcopy_init(struct hv_util_service *);
742void hv_fcopy_deinit(void); 743void hv_fcopy_deinit(void);
743void hv_fcopy_onchannelcallback(void *); 744void hv_fcopy_onchannelcallback(void *);
745void vmbus_initiate_unload(void);
744 746
745static inline void hv_poll_channel(struct vmbus_channel *channel, 747static inline void hv_poll_channel(struct vmbus_channel *channel,
746 void (*cb)(void *)) 748 void (*cb)(void *))
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 7870a906365e..2b56260b0eb4 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1106,6 +1106,7 @@ static void __exit vmbus_exit(void)
1106 1106
1107 vmbus_connection.conn_state = DISCONNECTED; 1107 vmbus_connection.conn_state = DISCONNECTED;
1108 hv_synic_clockevents_cleanup(); 1108 hv_synic_clockevents_cleanup();
1109 vmbus_disconnect();
1109 hv_remove_vmbus_irq(); 1110 hv_remove_vmbus_irq();
1110 vmbus_free_channels(); 1111 vmbus_free_channels();
1111 if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { 1112 if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
@@ -1118,7 +1119,6 @@ static void __exit vmbus_exit(void)
1118 smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1); 1119 smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
1119 acpi_bus_unregister_driver(&vmbus_acpi_driver); 1120 acpi_bus_unregister_driver(&vmbus_acpi_driver);
1120 hv_cpu_hotplug_quirk(false); 1121 hv_cpu_hotplug_quirk(false);
1121 vmbus_disconnect();
1122} 1122}
1123 1123
1124 1124