Implement the protocol for tearing down the monitor state established with the host. Signed-off-by: K. Y. Srinivasan <kys@xxxxxxxxxxxxx> --- drivers/hv/channel_mgmt.c | 25 +++++++++++++++++++++++++ drivers/hv/connection.c | 5 +++++ drivers/hv/hyperv_vmbus.h | 2 ++ include/linux/hyperv.h | 1 + 4 files changed, 33 insertions(+), 0 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 865a3af..4b9d89a 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 } /* + * vmbus_unload_response - Handler for the unload response. + */ +static void vmbus_unload_response(struct vmbus_channel_message_header *hdr) +{ + /* + * This is a global event; just wakeup the waiting thread. + * Once we successfully unload, we can cleanup the monitor state. + */ + complete(&vmbus_connection.unload_event); +} + +void vmbus_initiate_unload(void) +{ + struct vmbus_channel_message_header hdr; + + init_completion(&vmbus_connection.unload_event); + memset(&hdr, 0, sizeof(struct vmbus_channel_message_header)); + hdr.msgtype = CHANNELMSG_UNLOAD; + vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header)); + + wait_for_completion(&vmbus_connection.unload_event); +} + +/* * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. * */ @@ -717,6 +741,7 @@ struct vmbus_channel_message_table_entry {CHANNELMSG_INITIATE_CONTACT, 0, NULL}, {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response}, {CHANNELMSG_UNLOAD, 0, NULL}, + {CHANNELMSG_UNLOAD_RESPONSE, 1, vmbus_unload_response}, }; /* diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index b27220a..acd50e9 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -227,6 +227,11 @@ cleanup: void vmbus_disconnect(void) { + /* + * First send the unload request to the host. + */ + vmbus_initiate_unload(); + if (vmbus_connection.work_queue) { drain_workqueue(vmbus_connection.work_queue); destroy_workqueue(vmbus_connection.work_queue); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 138d663..cddc0c9 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -647,6 +647,7 @@ struct vmbus_connection { atomic_t next_gpadl_handle; + struct completion unload_event; /* * Represents channel interrupts. Each bit position represents a * channel. When a channel sends an interrupt via VMBUS, it finds its @@ -741,6 +742,7 @@ void hv_vss_onchannelcallback(void *); int hv_fcopy_init(struct hv_util_service *); void hv_fcopy_deinit(void); void hv_fcopy_onchannelcallback(void *); +void vmbus_initiate_unload(void); static inline void hv_poll_channel(struct vmbus_channel *channel, void (*cb)(void *)) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index e29ccdd..ea93486 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -389,6 +389,7 @@ enum vmbus_channel_message_type { CHANNELMSG_INITIATE_CONTACT = 14, CHANNELMSG_VERSION_RESPONSE = 15, CHANNELMSG_UNLOAD = 16, + CHANNELMSG_UNLOAD_RESPONSE = 17, CHANNELMSG_COUNT }; -- 1.7.4.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel