diff options
-rw-r--r-- | drivers/hv/connection.c | 17 | ||||
-rw-r--r-- | drivers/hv/hyperv_vmbus.h | 1 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 6 |
3 files changed, 19 insertions, 5 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index a63a795300b9..c4acd1ce7c0c 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -216,10 +216,21 @@ int vmbus_connect(void) cleanup: pr_err("Unable to connect to host\n"); + vmbus_connection.conn_state = DISCONNECTED; + vmbus_disconnect(); + + kfree(msginfo); + + return ret; +} - if (vmbus_connection.work_queue) +void vmbus_disconnect(void) +{ + if (vmbus_connection.work_queue) { + drain_workqueue(vmbus_connection.work_queue); destroy_workqueue(vmbus_connection.work_queue); + } if (vmbus_connection.int_page) { free_pages((unsigned long)vmbus_connection.int_page, 0); @@ -230,10 +241,6 @@ cleanup: free_pages((unsigned long)vmbus_connection.monitor_pages[1], 0); vmbus_connection.monitor_pages[0] = NULL; vmbus_connection.monitor_pages[1] = NULL; - - kfree(msginfo); - - return ret; } /* diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 44b1c9424712..6cf2de9f487a 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -692,6 +692,7 @@ void vmbus_free_channels(void); /* Connection interface */ int vmbus_connect(void); +void vmbus_disconnect(void); int vmbus_post_msg(void *buffer, size_t buflen); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e334ccc70582..76db97de09fd 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -574,6 +574,10 @@ static void vmbus_onmessage_work(struct work_struct *work) { struct onmessage_work_context *ctx; + /* Do not process messages if we're in DISCONNECTED state */ + if (vmbus_connection.conn_state == DISCONNECTED) + return; + ctx = container_of(work, struct onmessage_work_context, work); vmbus_onmessage(&ctx->msg); @@ -1025,12 +1029,14 @@ cleanup: static void __exit vmbus_exit(void) { + vmbus_connection.conn_state = DISCONNECTED; hv_remove_vmbus_irq(); vmbus_free_channels(); bus_unregister(&hv_bus); hv_cleanup(); acpi_bus_unregister_driver(&vmbus_acpi_driver); hv_cpu_hotplug_quirk(false); + vmbus_disconnect(); } |