diff options
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hv/channel_mgmt.c | 12 | ||||
-rw-r--r-- | drivers/hv/hv.c | 8 | ||||
-rw-r--r-- | drivers/hv/hyperv_vmbus.h | 1 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 30 |
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 @@ | |||
1 | menu "Microsoft Hyper-V guest support" | ||
2 | |||
1 | config HYPERV | 3 | config 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 | 16 | endmenu | |
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 | ||
226 | void 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 | ||
612 | struct vmbus_channel *relid2channel(u32 relid); | 612 | struct vmbus_channel *relid2channel(u32 relid); |
613 | 613 | ||
614 | void 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 | ||
65 | static int vmbus_exists(void) | ||
66 | { | ||
67 | if (hv_acpi_dev == NULL) | ||
68 | return -ENODEV; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
65 | 73 | ||
66 | static void get_channel_info(struct hv_device *device, | 74 | static 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 | } |
620 | EXPORT_SYMBOL_GPL(vmbus_driver_unregister); | 632 | EXPORT_SYMBOL_GPL(vmbus_driver_unregister); |
621 | 633 | ||
@@ -776,11 +788,23 @@ static int __init hv_acpi_init(void) | |||
776 | 788 | ||
777 | cleanup: | 789 | cleanup: |
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 | ||
795 | static 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 | ||
783 | MODULE_LICENSE("GPL"); | 806 | MODULE_LICENSE("GPL"); |
784 | MODULE_VERSION(HV_DRV_VERSION); | 807 | MODULE_VERSION(HV_DRV_VERSION); |
785 | 808 | ||
786 | module_init(hv_acpi_init); | 809 | subsys_initcall(hv_acpi_init); |
810 | module_exit(vmbus_exit); | ||