aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/Kconfig4
-rw-r--r--drivers/hv/channel_mgmt.c12
-rw-r--r--drivers/hv/hv.c8
-rw-r--r--drivers/hv/hyperv_vmbus.h1
-rw-r--r--drivers/hv/vmbus_drv.c30
5 files changed, 46 insertions, 9 deletions
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 9fa09ac000ad..70f5dde1cc52 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -1,3 +1,5 @@
1menu "Microsoft Hyper-V guest support"
2
1config HYPERV 3config HYPERV
2 tristate "Microsoft Hyper-V client drivers" 4 tristate "Microsoft Hyper-V client drivers"
3 depends on X86 && ACPI && PCI 5 depends on X86 && ACPI && PCI
@@ -11,4 +13,4 @@ config HYPERV_UTILS
11 help 13 help
12 Select this option to enable the Hyper-V Utilities. 14 Select this option to enable the Hyper-V Utilities.
13 15
14 16endmenu
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 12b85ff957fd..36484db36baf 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -223,6 +223,17 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
223 vmbus_device_unregister(channel->device_obj); 223 vmbus_device_unregister(channel->device_obj);
224} 224}
225 225
226void vmbus_free_channels(void)
227{
228 struct vmbus_channel *channel;
229
230 list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
231 vmbus_device_unregister(channel->device_obj);
232 kfree(channel->device_obj);
233 free_channel(channel);
234 }
235}
236
226/* 237/*
227 * vmbus_process_offer - Process the offer by creating a channel/device 238 * vmbus_process_offer - Process the offer by creating a channel/device
228 * associated with this offer 239 * associated with this offer
@@ -287,6 +298,7 @@ static void vmbus_process_offer(struct work_struct *work)
287 spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 298 spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
288 list_del(&newchannel->listentry); 299 list_del(&newchannel->listentry);
289 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 300 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
301 kfree(newchannel->device_obj);
290 302
291 free_channel(newchannel); 303 free_channel(newchannel);
292 } else { 304 } else {
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 0fb100ed91a3..12aa97f31f93 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -164,11 +164,6 @@ int hv_init(void)
164 164
165 max_leaf = query_hypervisor_info(); 165 max_leaf = query_hypervisor_info();
166 166
167 rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
168
169 if (hv_context.guestid != 0)
170 goto cleanup;
171
172 /* Write our OS info */ 167 /* Write our OS info */
173 wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); 168 wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
174 hv_context.guestid = HV_LINUX_GUEST_ID; 169 hv_context.guestid = HV_LINUX_GUEST_ID;
@@ -237,6 +232,9 @@ void hv_cleanup(void)
237{ 232{
238 union hv_x64_msr_hypercall_contents hypercall_msr; 233 union hv_x64_msr_hypercall_contents hypercall_msr;
239 234
235 /* Reset our OS id */
236 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
237
240 kfree(hv_context.signal_event_buffer); 238 kfree(hv_context.signal_event_buffer);
241 hv_context.signal_event_buffer = NULL; 239 hv_context.signal_event_buffer = NULL;
242 hv_context.signal_event_param = NULL; 240 hv_context.signal_event_param = NULL;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 0aee1122734c..6d7d286d5440 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -611,6 +611,7 @@ void vmbus_device_unregister(struct hv_device *device_obj);
611 611
612struct vmbus_channel *relid2channel(u32 relid); 612struct vmbus_channel *relid2channel(u32 relid);
613 613
614void vmbus_free_channels(void);
614 615
615/* Connection interface */ 616/* Connection interface */
616 617
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 0c048dd8013f..a220e5746d67 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -62,6 +62,14 @@ struct hv_device_info {
62 struct hv_dev_port_info outbound; 62 struct hv_dev_port_info outbound;
63}; 63};
64 64
65static int vmbus_exists(void)
66{
67 if (hv_acpi_dev == NULL)
68 return -ENODEV;
69
70 return 0;
71}
72
65 73
66static void get_channel_info(struct hv_device *device, 74static void get_channel_info(struct hv_device *device,
67 struct hv_device_info *info) 75 struct hv_device_info *info)
@@ -590,6 +598,10 @@ int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, c
590 598
591 pr_info("registering driver %s\n", hv_driver->name); 599 pr_info("registering driver %s\n", hv_driver->name);
592 600
601 ret = vmbus_exists();
602 if (ret < 0)
603 return ret;
604
593 hv_driver->driver.name = hv_driver->name; 605 hv_driver->driver.name = hv_driver->name;
594 hv_driver->driver.owner = owner; 606 hv_driver->driver.owner = owner;
595 hv_driver->driver.mod_name = mod_name; 607 hv_driver->driver.mod_name = mod_name;
@@ -614,8 +626,8 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver)
614{ 626{
615 pr_info("unregistering driver %s\n", hv_driver->name); 627 pr_info("unregistering driver %s\n", hv_driver->name);
616 628
617 driver_unregister(&hv_driver->driver); 629 if (!vmbus_exists())
618 630 driver_unregister(&hv_driver->driver);
619} 631}
620EXPORT_SYMBOL_GPL(vmbus_driver_unregister); 632EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
621 633
@@ -776,11 +788,23 @@ static int __init hv_acpi_init(void)
776 788
777cleanup: 789cleanup:
778 acpi_bus_unregister_driver(&vmbus_acpi_driver); 790 acpi_bus_unregister_driver(&vmbus_acpi_driver);
791 hv_acpi_dev = NULL;
779 return ret; 792 return ret;
780} 793}
781 794
795static void __exit vmbus_exit(void)
796{
797
798 free_irq(irq, hv_acpi_dev);
799 vmbus_free_channels();
800 bus_unregister(&hv_bus);
801 hv_cleanup();
802 acpi_bus_unregister_driver(&vmbus_acpi_driver);
803}
804
782 805
783MODULE_LICENSE("GPL"); 806MODULE_LICENSE("GPL");
784MODULE_VERSION(HV_DRV_VERSION); 807MODULE_VERSION(HV_DRV_VERSION);
785 808
786module_init(hv_acpi_init); 809subsys_initcall(hv_acpi_init);
810module_exit(vmbus_exit);