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/hv_kvp.c | 10 | ||||
-rw-r--r-- | drivers/hv/hyperv_vmbus.h | 1 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 30 |
6 files changed, 52 insertions, 13 deletions
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 9fa09ac000a..70f5dde1cc5 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -1,3 +1,5 @@ +menu "Microsoft Hyper-V guest support" + config HYPERV tristate "Microsoft Hyper-V client drivers" depends on X86 && ACPI && PCI @@ -11,4 +13,4 @@ config HYPERV_UTILS help Select this option to enable the Hyper-V Utilities. - +endmenu diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 12b85ff957f..36484db36ba 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) vmbus_device_unregister(channel->device_obj); } +void vmbus_free_channels(void) +{ + struct vmbus_channel *channel; + + list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { + vmbus_device_unregister(channel->device_obj); + kfree(channel->device_obj); + free_channel(channel); + } +} + /* * vmbus_process_offer - Process the offer by creating a channel/device * associated with this offer @@ -287,6 +298,7 @@ static void vmbus_process_offer(struct work_struct *work) spin_lock_irqsave(&vmbus_connection.channel_lock, flags); list_del(&newchannel->listentry); spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); + kfree(newchannel->device_obj); free_channel(newchannel); } else { diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 0fb100ed91a..12aa97f31f9 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -164,11 +164,6 @@ int hv_init(void) max_leaf = query_hypervisor_info(); - rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); - - if (hv_context.guestid != 0) - goto cleanup; - /* Write our OS info */ wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); hv_context.guestid = HV_LINUX_GUEST_ID; @@ -237,6 +232,9 @@ void hv_cleanup(void) { union hv_x64_msr_hypercall_contents hypercall_msr; + /* Reset our OS id */ + wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); + kfree(hv_context.signal_event_buffer); hv_context.signal_event_buffer = NULL; hv_context.signal_event_param = NULL; diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 89f52440fcf..0e8343f585b 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -212,11 +212,13 @@ kvp_respond_to_host(char *key, char *value, int error) * The windows host expects the key/value pair to be encoded * in utf16. */ - keylen = utf8s_to_utf16s(key_name, strlen(key_name), - (wchar_t *)kvp_data->data.key); + keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN, + (wchar_t *) kvp_data->data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2); kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ - valuelen = utf8s_to_utf16s(value, strlen(value), - (wchar_t *)kvp_data->data.value); + valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, + (wchar_t *) kvp_data->data.value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2); kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ kvp_data->data.value_type = REG_SZ; /* all our values are strings */ diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 0aee1122734..6d7d286d544 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); struct vmbus_channel *relid2channel(u32 relid); +void vmbus_free_channels(void); /* Connection interface */ diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0c048dd8013..a220e5746d6 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -62,6 +62,14 @@ struct hv_device_info { struct hv_dev_port_info outbound; }; +static int vmbus_exists(void) +{ + if (hv_acpi_dev == NULL) + return -ENODEV; + + return 0; +} + static void get_channel_info(struct hv_device *device, struct hv_device_info *info) @@ -590,6 +598,10 @@ int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, c pr_info("registering driver %s\n", hv_driver->name); + ret = vmbus_exists(); + if (ret < 0) + return ret; + hv_driver->driver.name = hv_driver->name; hv_driver->driver.owner = owner; hv_driver->driver.mod_name = mod_name; @@ -614,8 +626,8 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) { pr_info("unregistering driver %s\n", hv_driver->name); - driver_unregister(&hv_driver->driver); - + if (!vmbus_exists()) + driver_unregister(&hv_driver->driver); } EXPORT_SYMBOL_GPL(vmbus_driver_unregister); @@ -776,11 +788,23 @@ static int __init hv_acpi_init(void) cleanup: acpi_bus_unregister_driver(&vmbus_acpi_driver); + hv_acpi_dev = NULL; return ret; } +static void __exit vmbus_exit(void) +{ + + free_irq(irq, hv_acpi_dev); + vmbus_free_channels(); + bus_unregister(&hv_bus); + hv_cleanup(); + acpi_bus_unregister_driver(&vmbus_acpi_driver); +} + MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); -module_init(hv_acpi_init); +subsys_initcall(hv_acpi_init); +module_exit(vmbus_exit); |