From 2dda95f80b2afa4bf85c6419f40e11b545cda422 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 15 Jul 2011 13:38:56 -0700 Subject: Staging: hv: vmbus: Don't wait indefinitely for IRQ resouces If an attempt is made to load the vmbus driver on a non-Hyper-V platform, the load operation will hang since we currently wait indefinitely to retrieve the IRQ information. This is done in the context of an acpi callback context (which will obviously not happen when this driver is loaded on a non-Hyper-V platform). This patch fixes the problem. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 1c949f5..67a4f33 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -768,7 +768,7 @@ MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); static int __init hv_acpi_init(void) { - int ret; + int ret, t; init_completion(&probe_event); @@ -781,16 +781,25 @@ static int __init hv_acpi_init(void) if (ret) return ret; - wait_for_completion(&probe_event); + t = wait_for_completion_timeout(&probe_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } if (irq <= 0) { - acpi_bus_unregister_driver(&vmbus_acpi_driver); - return -ENODEV; + ret = -ENODEV; + goto cleanup; } ret = vmbus_bus_init(irq); if (ret) - acpi_bus_unregister_driver(&vmbus_acpi_driver); + goto cleanup; + + return 0; + +cleanup: + acpi_bus_unregister_driver(&vmbus_acpi_driver); return ret; } -- cgit v1.1 From 064931d0bb088c56e80d427e91a812ee7dd8c7dc Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 19 Jul 2011 11:44:20 -0700 Subject: Staging: hv: tools: Fix a checkpatch warning in hv_kvp_daemon.c Fix a checkpatch warning in hv_kvp_daemon.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/tools/hv_kvp_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c index a4a407f..8fd0f2b 100644 --- a/drivers/staging/hv/tools/hv_kvp_daemon.c +++ b/drivers/staging/hv/tools/hv_kvp_daemon.c @@ -116,7 +116,7 @@ void kvp_get_os_info(void) uname(&uts_buf); os_build = uts_buf.release; - processor_arch= uts_buf.machine; + processor_arch = uts_buf.machine; file = fopen("/etc/SuSE-release", "r"); if (file != NULL) -- cgit v1.1 From dec317fd6accfdba4daff13aa4d9f5abde02b347 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 19 Jul 2011 11:44:21 -0700 Subject: Staging: hv: vmbus: Fix checkpatch warnings Fix checkpatch warnings in hv.c Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c index 824f816..2192d78 100644 --- a/drivers/staging/hv/hv.c +++ b/drivers/staging/hv/hv.c @@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) u64 hv_status = 0; u64 input_address = (input) ? virt_to_phys(input) : 0; u64 output_address = (output) ? virt_to_phys(output) : 0; - volatile void *hypercall_page = hv_context.hypercall_page; + void *hypercall_page = hv_context.hypercall_page; __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); __asm__ __volatile__("call *%3" : "=a" (hv_status) : @@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) u64 output_address = (output) ? virt_to_phys(output) : 0; u32 output_address_hi = output_address >> 32; u32 output_address_lo = output_address & 0xFFFFFFFF; - volatile void *hypercall_page = hv_context.hypercall_page; + void *hypercall_page = hv_context.hypercall_page; __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), "=a"(hv_status_lo) : "d" (control_hi), -- cgit v1.1 From e54bbc6471d7f788d829e5f3b5922960048fbff7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 22 Jul 2011 10:14:31 -0700 Subject: Staging: hv: util: kvp: Fix the reported OSVersion string The current win7 host does not like it when we return the complete kernel release information. Conform to what the host expects. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/tools/hv_kvp_daemon.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c index 8fd0f2b..c4cf988 100644 --- a/drivers/staging/hv/tools/hv_kvp_daemon.c +++ b/drivers/staging/hv/tools/hv_kvp_daemon.c @@ -118,6 +118,15 @@ void kvp_get_os_info(void) os_build = uts_buf.release; processor_arch = uts_buf.machine; + /* + * The current windows host (win7) expects the build + * string to be of the form: x.y.z + * Strip additional information we may have. + */ + p = strchr(os_build, '-'); + if (p) + *p = '\0'; + file = fopen("/etc/SuSE-release", "r"); if (file != NULL) goto kvp_osinfo_found; -- cgit v1.1 From 5be528c2130a1281ba858296924dd619068bb0e3 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 26 Jul 2011 11:03:10 -0700 Subject: Staging: hv: util: kvp: Cleanup kvp_get_domain_name() Cleanup kvp_get_domain_name(). If getaddrinfo() fails, deal with it properly (this can happen if no IP address has been assigned). Also, don't specify a specific service in the call to getaddrinfo() to make this code as generic as possible. Lastly, move the call to gethostname() after the local variables. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/tools/hv_kvp_daemon.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c index c4cf988..11224ed 100644 --- a/drivers/staging/hv/tools/hv_kvp_daemon.c +++ b/drivers/staging/hv/tools/hv_kvp_daemon.c @@ -273,22 +273,20 @@ static int kvp_get_domain_name(char *buffer, int length) { struct addrinfo hints, *info ; - gethostname(buffer, length); int error = 0; + gethostname(buffer, length); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; - error = getaddrinfo(buffer, "http", &hints, &info); + error = getaddrinfo(buffer, NULL, &hints, &info); if (error != 0) { strcpy(buffer, "getaddrinfo failed\n"); - error = 1; - goto get_domain_done; + return error; } strcpy(buffer, info->ai_canonname); -get_domain_done: freeaddrinfo(info); return error; } -- cgit v1.1 From dbbb24947e1bea5e6034ae2edfbf1be5b8f2b062 Mon Sep 17 00:00:00 2001 From: Ruslan Pisarev Date: Fri, 22 Jul 2011 15:12:47 +0300 Subject: Staging: hv: Fix macros, tab errors and warning in drivers/staging/hv/hv_mouse.c This is a patch to the hv_mouse.c file that fixed up macros, tab errors and warning found by the checkpatch.pl tools. Signed-off-by: Ruslan Pisarev Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index d957fc2..9f3fbee 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -54,7 +54,7 @@ struct hv_input_dev_info { (SYNTHHID_INPUT_VERSION_MAJOR << 16)) -#pragma pack(push,1) +#pragma pack(push, 1) /* * Message types in the synthetic input protocol */ @@ -120,8 +120,8 @@ struct synthhid_input_report { #pragma pack(pop) -#define INPUTVSC_SEND_RING_BUFFER_SIZE 10*PAGE_SIZE -#define INPUTVSC_RECV_RING_BUFFER_SIZE 10*PAGE_SIZE +#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) +#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) #define NBITS(x) (((x)/BITS_PER_LONG)+1) @@ -509,22 +509,22 @@ static void mousevsc_on_channel_callback(void *context) desc = (struct vmpacket_descriptor *)buffer; switch (desc->type) { - case VM_PKT_COMP: - mousevsc_on_send_completion( - device, desc); - break; - - case VM_PKT_DATA_INBAND: - mousevsc_on_receive( - device, desc); - break; - - default: - pr_err("unhandled packet type %d, tid %llx len %d\n", - desc->type, - req_id, - bytes_recvd); - break; + case VM_PKT_COMP: + mousevsc_on_send_completion( + device, desc); + break; + + case VM_PKT_DATA_INBAND: + mousevsc_on_receive( + device, desc); + break; + + default: + pr_err("unhandled packet type %d, tid %llx len %d\n", + desc->type, + req_id, + bytes_recvd); + break; } /* reset */ @@ -960,7 +960,7 @@ static void __exit mousevsc_exit(void) * installed and/or configured. We don't do anything else with the table, but * it needs to be present. */ -const static struct pci_device_id microsoft_hv_pci_table[] = { +static const struct pci_device_id microsoft_hv_pci_table[] = { { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ { 0 } }; -- cgit v1.1 From 32a753ffb2c5aea6c32d34393a8e0da3ecfd78bb Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:27 -0700 Subject: Staging: hv: vmbus: VMBUS is an ACPI enumerated device, get rid of the PCI signature VMBUS is an ACPI enumerated device, get rid of the PCI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 67a4f33..8f1d6eb 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -754,18 +753,6 @@ static struct acpi_driver vmbus_acpi_driver = { }, }; -/* - * We use a PCI table to determine if we should autoload this driver This is - * needed by distro tools to determine if the hyperv drivers should be - * installed and/or configured. We don't do anything else with the table, but - * it needs to be present. - */ -static const struct pci_device_id microsoft_hv_pci_table[] = { - { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); - static int __init hv_acpi_init(void) { int ret, t; -- cgit v1.1 From 358d2ee2e8f5c25f1661e94c206102c88fdee370 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:28 -0700 Subject: Staging: hv: Replace struct hv_guid with the uuid type already defined in Linux Replace struct hv_guid with the uuid type already defined in Linux. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 18 ++--- drivers/staging/hv/channel.c | 4 +- drivers/staging/hv/channel_mgmt.c | 50 ++++++-------- drivers/staging/hv/hv_mouse.c | 6 +- drivers/staging/hv/hyperv.h | 24 +++---- drivers/staging/hv/hyperv_vmbus.h | 8 +-- drivers/staging/hv/netvsc.c | 6 +- drivers/staging/hv/storvsc_drv.c | 6 +- drivers/staging/hv/vmbus_drv.c | 142 +++++++++++++++++++------------------- 9 files changed, 129 insertions(+), 135 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index d286b22..018b293 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -112,8 +112,8 @@ struct block_device_context { static const char *drv_name = "blkvsc"; /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ -static const struct hv_guid dev_type = { - .data = { +static const uuid_le dev_type = { + .b = { 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 } @@ -155,13 +155,13 @@ static int blkvsc_device_add(struct hv_device *device, * id. For IDE devices, the device instance id is formatted as * * - - 8899 - 000000000000. */ - device_info->path_id = device->dev_instance.data[3] << 24 | - device->dev_instance.data[2] << 16 | - device->dev_instance.data[1] << 8 | - device->dev_instance.data[0]; + device_info->path_id = device->dev_instance.b[3] << 24 | + device->dev_instance.b[2] << 16 | + device->dev_instance.b[1] << 8 | + device->dev_instance.b[0]; - device_info->target_id = device->dev_instance.data[5] << 8 | - device->dev_instance.data[4]; + device_info->target_id = device->dev_instance.b[5] << 8 | + device->dev_instance.b[4]; return ret; } @@ -829,7 +829,7 @@ static int blkvsc_drv_init(void) BUILD_BUG_ON(sizeof(sector_t) != 8); - memcpy(&drv->dev_type, &dev_type, sizeof(struct hv_guid)); + memcpy(&drv->dev_type, &dev_type, sizeof(uuid_le)); drv->driver.name = drv_name; /* The driver belongs to vmbus */ diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index 455f47a..222adcc 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -81,10 +81,10 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, debuginfo->relid = channel->offermsg.child_relid; debuginfo->state = channel->state; memcpy(&debuginfo->interfacetype, - &channel->offermsg.offer.if_type, sizeof(struct hv_guid)); + &channel->offermsg.offer.if_type, sizeof(uuid_le)); memcpy(&debuginfo->interface_instance, &channel->offermsg.offer.if_instance, - sizeof(struct hv_guid)); + sizeof(uuid_le)); monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index bf011f3..11beb41c 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -40,12 +40,12 @@ struct vmbus_channel_message_table_entry { #define MAX_MSG_TYPES 4 #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 -static const struct hv_guid +static const uuid_le supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ /* Storage - SCSI */ { - .data = { + .b = { 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f } @@ -54,7 +54,7 @@ static const struct hv_guid /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ /* Network */ { - .data = { + .b = { 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E } @@ -63,7 +63,7 @@ static const struct hv_guid /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ /* Input */ { - .data = { + .b = { 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A } @@ -72,7 +72,7 @@ static const struct hv_guid /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ /* IDE */ { - .data = { + .b = { 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 } @@ -80,7 +80,7 @@ static const struct hv_guid /* 0E0B6031-5213-4934-818B-38D90CED39DB */ /* Shutdown */ { - .data = { + .b = { 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB } @@ -88,7 +88,7 @@ static const struct hv_guid /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ /* TimeSync */ { - .data = { + .b = { 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } @@ -96,7 +96,7 @@ static const struct hv_guid /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ /* Heartbeat */ { - .data = { + .b = { 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d } @@ -104,7 +104,7 @@ static const struct hv_guid /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ /* KVP */ { - .data = { + .b = { 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 } @@ -231,7 +231,7 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { /* Shutdown */ { .msg_type = HV_SHUTDOWN_MSG, - .data = { + .data.b = { 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB }, @@ -242,7 +242,7 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { /* TimeSync */ { .msg_type = HV_TIMESYNC_MSG, - .data = { + .data.b = { 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf }, @@ -252,7 +252,7 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { /* Heartbeat */ { .msg_type = HV_HEARTBEAT_MSG, - .data = { + .data.b = { 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d }, @@ -261,7 +261,7 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ /* KVP */ { - .data = { + .data.b = { 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 }, @@ -358,12 +358,10 @@ static void vmbus_process_offer(struct work_struct *work) spin_lock_irqsave(&vmbus_connection.channel_lock, flags); list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { - if (!memcmp(&channel->offermsg.offer.if_type, - &newchannel->offermsg.offer.if_type, - sizeof(struct hv_guid)) && - !memcmp(&channel->offermsg.offer.if_instance, - &newchannel->offermsg.offer.if_instance, - sizeof(struct hv_guid))) { + if (!uuid_le_cmp(channel->offermsg.offer.if_type, + newchannel->offermsg.offer.if_type) && + !uuid_le_cmp(channel->offermsg.offer.if_instance, + newchannel->offermsg.offer.if_instance)) { fnew = false; break; } @@ -416,9 +414,8 @@ static void vmbus_process_offer(struct work_struct *work) /* Open IC channels */ for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) { - if (memcmp(&newchannel->offermsg.offer.if_type, - &hv_cb_utils[cnt].data, - sizeof(struct hv_guid)) == 0 && + if (!uuid_le_cmp(newchannel->offermsg.offer.if_type, + hv_cb_utils[cnt].data) && vmbus_open(newchannel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, chn_cb_negotiate, @@ -444,16 +441,15 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) { struct vmbus_channel_offer_channel *offer; struct vmbus_channel *newchannel; - struct hv_guid *guidtype; - struct hv_guid *guidinstance; + uuid_le *guidtype; + uuid_le *guidinstance; int i; int fsupported = 0; offer = (struct vmbus_channel_offer_channel *)hdr; for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { - if (memcmp(&offer->offer.if_type, - &supported_device_classes[i], - sizeof(struct hv_guid)) == 0) { + if (!uuid_le_cmp(offer->offer.if_type, + supported_device_classes[i])) { fsupported = 1; break; } diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 9f3fbee..950f4b4 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -179,8 +179,8 @@ struct mousevsc_dev { static const char *driver_name = "mousevsc"; /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ -static const struct hv_guid mouse_guid = { - .data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, +static const uuid_le mouse_guid = { + .b = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A} }; @@ -932,7 +932,7 @@ static int __init mousevsc_init(void) DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing."); memcpy(&drv->dev_type, &mouse_guid, - sizeof(struct hv_guid)); + sizeof(uuid_le)); drv->driver.name = driver_name; diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index 1747a24..399d9fe 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -35,9 +36,6 @@ #include -struct hv_guid { - unsigned char data[16]; -}; #define MAX_PAGE_BUFFER_COUNT 16 #define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */ @@ -156,8 +154,8 @@ struct hv_ring_buffer_debug_info { * struct contains the fundamental information about an offer. */ struct vmbus_channel_offer { - struct hv_guid if_type; - struct hv_guid if_instance; + uuid_le if_type; + uuid_le if_instance; u64 int_latency; /* in 100ns units */ u32 if_revision; u32 server_ctx_size; /* in bytes */ @@ -526,8 +524,8 @@ enum vmbus_channel_state { struct vmbus_channel_debug_info { u32 relid; enum vmbus_channel_state state; - struct hv_guid interfacetype; - struct hv_guid interface_instance; + uuid_le interfacetype; + uuid_le interface_instance; u32 monitorid; u32 servermonitor_pending; u32 servermonitor_latency; @@ -786,8 +784,8 @@ struct hv_dev_port_info { struct hv_device_info { u32 chn_id; u32 chn_state; - struct hv_guid chn_type; - struct hv_guid chn_instance; + uuid_le chn_type; + uuid_le chn_instance; u32 monitor_id; u32 server_monitor_pending; @@ -806,7 +804,7 @@ struct hv_driver { const char *name; /* the device type supported by this driver */ - struct hv_guid dev_type; + uuid_le dev_type; struct device_driver driver; @@ -819,10 +817,10 @@ struct hv_driver { /* Base device object */ struct hv_device { /* the device type id of this device */ - struct hv_guid dev_type; + uuid_le dev_type; /* the device instance id of this device */ - struct hv_guid dev_instance; + uuid_le dev_instance; struct device device; @@ -935,7 +933,7 @@ struct ictimesync_data { struct hyperv_service_callback { u8 msg_type; char *log_msg; - unsigned char data[16]; + uuid_le data; struct vmbus_channel *channel; void (*callback) (void *context); }; diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h index 349ad80..16ca90d 100644 --- a/drivers/staging/hv/hyperv_vmbus.h +++ b/drivers/staging/hv/hyperv_vmbus.h @@ -451,8 +451,8 @@ enum { /* #define VMBUS_PORT_ID 11 */ /* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */ -static const struct hv_guid VMBUS_SERVICE_ID = { - .data = { +static const uuid_le VMBUS_SERVICE_ID = { + .b = { 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4 }, @@ -601,8 +601,8 @@ extern struct vmbus_connection vmbus_connection; /* General vmbus interface */ -struct hv_device *vmbus_child_device_create(struct hv_guid *type, - struct hv_guid *instance, +struct hv_device *vmbus_child_device_create(uuid_le *type, + uuid_le *instance, struct vmbus_channel *channel); int vmbus_child_device_register(struct hv_device *child_device_obj); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index dc5e5c4..1506b53 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -36,8 +36,8 @@ static const char *driver_name = "netvsc"; /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ -static const struct hv_guid netvsc_device_type = { - .data = { +static const uuid_le netvsc_device_type = { + .b = { 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E } @@ -1009,7 +1009,7 @@ int netvsc_initialize(struct hv_driver *drv) { drv->name = driver_name; - memcpy(&drv->dev_type, &netvsc_device_type, sizeof(struct hv_guid)); + memcpy(&drv->dev_type, &netvsc_device_type, sizeof(uuid_le)); return 0; } diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 7effaf3..e4cdbc5 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -45,8 +45,8 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); static const char *driver_name = "storvsc"; /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ -static const struct hv_guid stor_vsci_device_type = { - .data = { +static const uuid_le stor_vsci_device_type = { + .b = { 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f } @@ -765,7 +765,7 @@ static int __init storvsc_drv_init(void) sizeof(u64))); memcpy(&drv->dev_type, &stor_vsci_device_type, - sizeof(struct hv_guid)); + sizeof(uuid_le)); if (max_outstanding_req_per_channel < STORVSC_MAX_IO_REQUESTS) diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 8f1d6eb..c88a183 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -64,9 +64,9 @@ static void get_channel_info(struct hv_device *device, info->chn_id = debug_info.relid; info->chn_state = debug_info.state; memcpy(&info->chn_type, &debug_info.interfacetype, - sizeof(struct hv_guid)); + sizeof(uuid_le)); memcpy(&info->chn_instance, &debug_info.interface_instance, - sizeof(struct hv_guid)); + sizeof(uuid_le)); info->monitor_id = debug_info.monitorid; @@ -116,41 +116,41 @@ static ssize_t vmbus_show_device_attr(struct device *dev, if (!strcmp(dev_attr->attr.name, "class_id")) { return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info.chn_type.data[3], - device_info.chn_type.data[2], - device_info.chn_type.data[1], - device_info.chn_type.data[0], - device_info.chn_type.data[5], - device_info.chn_type.data[4], - device_info.chn_type.data[7], - device_info.chn_type.data[6], - device_info.chn_type.data[8], - device_info.chn_type.data[9], - device_info.chn_type.data[10], - device_info.chn_type.data[11], - device_info.chn_type.data[12], - device_info.chn_type.data[13], - device_info.chn_type.data[14], - device_info.chn_type.data[15]); + device_info.chn_type.b[3], + device_info.chn_type.b[2], + device_info.chn_type.b[1], + device_info.chn_type.b[0], + device_info.chn_type.b[5], + device_info.chn_type.b[4], + device_info.chn_type.b[7], + device_info.chn_type.b[6], + device_info.chn_type.b[8], + device_info.chn_type.b[9], + device_info.chn_type.b[10], + device_info.chn_type.b[11], + device_info.chn_type.b[12], + device_info.chn_type.b[13], + device_info.chn_type.b[14], + device_info.chn_type.b[15]); } else if (!strcmp(dev_attr->attr.name, "device_id")) { return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info.chn_instance.data[3], - device_info.chn_instance.data[2], - device_info.chn_instance.data[1], - device_info.chn_instance.data[0], - device_info.chn_instance.data[5], - device_info.chn_instance.data[4], - device_info.chn_instance.data[7], - device_info.chn_instance.data[6], - device_info.chn_instance.data[8], - device_info.chn_instance.data[9], - device_info.chn_instance.data[10], - device_info.chn_instance.data[11], - device_info.chn_instance.data[12], - device_info.chn_instance.data[13], - device_info.chn_instance.data[14], - device_info.chn_instance.data[15]); + device_info.chn_instance.b[3], + device_info.chn_instance.b[2], + device_info.chn_instance.b[1], + device_info.chn_instance.b[0], + device_info.chn_instance.b[5], + device_info.chn_instance.b[4], + device_info.chn_instance.b[7], + device_info.chn_instance.b[6], + device_info.chn_instance.b[8], + device_info.chn_instance.b[9], + device_info.chn_instance.b[10], + device_info.chn_instance.b[11], + device_info.chn_instance.b[12], + device_info.chn_instance.b[13], + device_info.chn_instance.b[14], + device_info.chn_instance.b[15]); } else if (!strcmp(dev_attr->attr.name, "state")) { return sprintf(buf, "%d\n", device_info.chn_state); } else if (!strcmp(dev_attr->attr.name, "id")) { @@ -246,22 +246,22 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={" "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}", - dev->dev_type.data[3], - dev->dev_type.data[2], - dev->dev_type.data[1], - dev->dev_type.data[0], - dev->dev_type.data[5], - dev->dev_type.data[4], - dev->dev_type.data[7], - dev->dev_type.data[6], - dev->dev_type.data[8], - dev->dev_type.data[9], - dev->dev_type.data[10], - dev->dev_type.data[11], - dev->dev_type.data[12], - dev->dev_type.data[13], - dev->dev_type.data[14], - dev->dev_type.data[15]); + dev->dev_type.b[3], + dev->dev_type.b[2], + dev->dev_type.b[1], + dev->dev_type.b[0], + dev->dev_type.b[5], + dev->dev_type.b[4], + dev->dev_type.b[7], + dev->dev_type.b[6], + dev->dev_type.b[8], + dev->dev_type.b[9], + dev->dev_type.b[10], + dev->dev_type.b[11], + dev->dev_type.b[12], + dev->dev_type.b[13], + dev->dev_type.b[14], + dev->dev_type.b[15]); if (ret) return ret; @@ -269,22 +269,22 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={" "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}", - dev->dev_instance.data[3], - dev->dev_instance.data[2], - dev->dev_instance.data[1], - dev->dev_instance.data[0], - dev->dev_instance.data[5], - dev->dev_instance.data[4], - dev->dev_instance.data[7], - dev->dev_instance.data[6], - dev->dev_instance.data[8], - dev->dev_instance.data[9], - dev->dev_instance.data[10], - dev->dev_instance.data[11], - dev->dev_instance.data[12], - dev->dev_instance.data[13], - dev->dev_instance.data[14], - dev->dev_instance.data[15]); + dev->dev_instance.b[3], + dev->dev_instance.b[2], + dev->dev_instance.b[1], + dev->dev_instance.b[0], + dev->dev_instance.b[5], + dev->dev_instance.b[4], + dev->dev_instance.b[7], + dev->dev_instance.b[6], + dev->dev_instance.b[8], + dev->dev_instance.b[9], + dev->dev_instance.b[10], + dev->dev_instance.b[11], + dev->dev_instance.b[12], + dev->dev_instance.b[13], + dev->dev_instance.b[14], + dev->dev_instance.b[15]); if (ret) return ret; @@ -303,7 +303,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver) /* We found our driver ? */ if (memcmp(&hv_dev->dev_type, &drv->dev_type, - sizeof(struct hv_guid)) == 0) + sizeof(uuid_le)) == 0) match = 1; return match; @@ -630,8 +630,8 @@ EXPORT_SYMBOL(vmbus_child_driver_unregister); * vmbus_child_device_create - Creates and registers a new child device * on the vmbus. */ -struct hv_device *vmbus_child_device_create(struct hv_guid *type, - struct hv_guid *instance, +struct hv_device *vmbus_child_device_create(uuid_le *type, + uuid_le *instance, struct vmbus_channel *channel) { struct hv_device *child_device_obj; @@ -644,9 +644,9 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type, } child_device_obj->channel = channel; - memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid)); + memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le)); memcpy(&child_device_obj->dev_instance, instance, - sizeof(struct hv_guid)); + sizeof(uuid_le)); return child_device_obj; -- cgit v1.1 From 2e2c1d17abc3953239bc05ac586eab9f2f14bfda Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:31 -0700 Subject: Staging: hv: vmbus: Introduce vmbus ID space in struct hv_driver In preparation for supporting auto-loading Hyper-V drivers using vmbus specific aliases, introduce vmbus ID space in struct hv_driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index 399d9fe..b8199f4 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -805,6 +806,7 @@ struct hv_driver { /* the device type supported by this driver */ uuid_le dev_type; + const struct hv_vmbus_device_id *id_table; struct device_driver driver; -- cgit v1.1 From eefd7f4555163da346781a2216264ba871aed76b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:32 -0700 Subject: Staging: hv: blkvsc: Use the newly introduced vmbus ID in the blockvsc driver Use the newly introduced vmbus ID in the blockvsc driver. Also, do the associated cleanup. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 018b293..9b99387 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -111,14 +111,6 @@ struct block_device_context { static const char *drv_name = "blkvsc"; -/* {32412632-86cb-44a2-9b5c-50d1417354f5} */ -static const uuid_le dev_type = { - .b = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } -}; - /* * There is a circular dependency involving blkvsc_request_completion() * and blkvsc_do_request(). @@ -802,10 +794,24 @@ static void blkvsc_request(struct request_queue *queue) } } +static const struct hv_vmbus_device_id id_table[] = { + { + /* IDE guid */ + .guid = { + 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 + } + }, + { + .guid = { } + }, +}; +MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver blkvsc_drv = { + .id_table = id_table, .probe = blkvsc_probe, .remove = blkvsc_remove, .shutdown = blkvsc_shutdown, @@ -829,7 +835,6 @@ static int blkvsc_drv_init(void) BUILD_BUG_ON(sizeof(sector_t) != 8); - memcpy(&drv->dev_type, &dev_type, sizeof(uuid_le)); drv->driver.name = drv_name; /* The driver belongs to vmbus */ -- cgit v1.1 From d847b5fe333d3cc588b26fabb138bb86077f080d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:33 -0700 Subject: Staging: hv: storvsc: Use the newly introduced vmbus ID in storvsc driver Use the newly introduced vmbus ID in storvsc driver. Also, do the assciated cleanup. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index e4cdbc5..ed2140c 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -44,14 +44,6 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); static const char *driver_name = "storvsc"; -/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ -static const uuid_le stor_vsci_device_type = { - .b = { - 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f - } -}; - struct hv_host_device { struct hv_device *dev; struct kmem_cache *request_pool; @@ -646,7 +638,20 @@ static struct scsi_host_template scsi_driver = { .dma_boundary = PAGE_SIZE-1, }; +static const struct hv_vmbus_device_id id_table[] = { + { + /* SCSI guid */ + .guid = { + 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, + 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f + } + }, + { + .guid = { } + }, +}; +MODULE_DEVICE_TABLE(vmbus, id_table); /* * storvsc_probe - Add a new device for this driver */ @@ -720,6 +725,7 @@ static int storvsc_probe(struct hv_device *device) /* The one and only one */ static struct hv_driver storvsc_drv = { + .id_table = id_table, .probe = storvsc_probe, .remove = storvsc_remove, }; @@ -764,9 +770,6 @@ static int __init storvsc_drv_init(void) sizeof(struct vstor_packet) + sizeof(u64), sizeof(u64))); - memcpy(&drv->dev_type, &stor_vsci_device_type, - sizeof(uuid_le)); - if (max_outstanding_req_per_channel < STORVSC_MAX_IO_REQUESTS) return -1; -- cgit v1.1 From 345c4cc3b953a43464776701918e22c7e30cedd0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:34 -0700 Subject: Staging: hv: netvsc: Use the newly introduced vmbus ID in netvsc driver Use the newly introduced vmbus ID in netvsc driver. Also, do the associated cleanup. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 10 ---------- drivers/staging/hv/netvsc_drv.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 1506b53..6f4541b 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -35,15 +35,6 @@ /* Globals */ static const char *driver_name = "netvsc"; -/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ -static const uuid_le netvsc_device_type = { - .b = { - 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E - } -}; - - static struct netvsc_device *alloc_net_device(struct hv_device *device) { struct netvsc_device *net_device; @@ -1009,7 +1000,6 @@ int netvsc_initialize(struct hv_driver *drv) { drv->name = driver_name; - memcpy(&drv->dev_type, &netvsc_device_type, sizeof(uuid_le)); return 0; } diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 61989f0..2e25c95 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -413,8 +413,24 @@ static int netvsc_remove(struct hv_device *dev) return 0; } +static const struct hv_vmbus_device_id id_table[] = { + { + /* Network guid */ + .guid = { + 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, + 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E + } + }, + { + .guid = { } + }, +}; + +MODULE_DEVICE_TABLE(vmbus, id_table); + /* The one and only one */ static struct hv_driver netvsc_drv = { + .id_table = id_table, .probe = netvsc_probe, .remove = netvsc_remove, }; -- cgit v1.1 From 1ec91ebe4da8fe016a16eec1177e8edb2ea57517 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:35 -0700 Subject: Staging: hv: mousevsc: Use the newly introduced vmbus ID in mouse driver Use the newly introduced vmbus ID in mouse driver. Also, do the associated cleanup. Since the mouse driver is not functional, we disable the autoloading of this driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 950f4b4..dd8a114 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -178,12 +178,6 @@ struct mousevsc_dev { static const char *driver_name = "mousevsc"; -/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ -static const uuid_le mouse_guid = { - .b = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, - 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A} -}; - static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info); static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); @@ -914,8 +908,26 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) kfree(hid_dev); } +static const struct hv_vmbus_device_id id_table[] = { + { + /* Mouse guid */ + .guid = { + 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, + 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A + } + }, + { + .guid = { } + }, +}; + +/* + * The mouse driver is not functional; do not auto-load it. + */ +/* MODULE_DEVICE_TABLE(vmbus, id_table); */ static struct hv_driver mousevsc_drv = { + .id_table = id_table, .probe = mousevsc_probe, .remove = mousevsc_remove, }; @@ -931,9 +943,6 @@ static int __init mousevsc_init(void) DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing."); - memcpy(&drv->dev_type, &mouse_guid, - sizeof(uuid_le)); - drv->driver.name = driver_name; /* The driver belongs to vmbus */ -- cgit v1.1 From 283f21294ea02f7608e0c833b9c982712427fc50 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:36 -0700 Subject: Staging: hv: util: Make hv_utils a vmbus device driver In preperation for supporting auto-loading the util driver, make the util driver a vmbus driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 64 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index c164b54..a620f4d 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -36,6 +36,8 @@ static u8 *shut_txf_buf; static u8 *time_txf_buf; static u8 *hbeat_txf_buf; +static const char *driver_name = "hv_util"; + static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; @@ -210,6 +212,63 @@ static void heartbeat_onchannelcallback(void *context) } } +/* + * The devices managed by the util driver don't need any additional + * setup. + */ +static int util_probe(struct hv_device *dev) +{ + return 0; +} + +static int util_remove(struct hv_device *dev) +{ + return 0; +} + +static const struct hv_vmbus_device_id id_table[] = { + { + /* Shutdown guid */ + .guid = { + 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB + } + }, + { + /* Time synch guid */ + .guid = { + 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, + 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf + } + }, + { + /* Heartbeat guid */ + .guid = { + 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d + } + }, + { + /* KVP guid */ + .guid = { + 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, + 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 + } + }, + { + .guid = { } + }, +}; + +MODULE_DEVICE_TABLE(vmbus, id_table); + +/* The one and only one */ +static struct hv_driver util_drv = { + .id_table = id_table, + .probe = util_probe, + .remove = util_remove, +}; + static const struct pci_device_id __initconst hv_utils_pci_table[] __maybe_unused = { { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ @@ -264,7 +323,9 @@ static int __init init_hyperv_utils(void) hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; - return 0; + util_drv.driver.name = driver_name; + + return vmbus_child_driver_register(&util_drv.driver); } static void exit_hyperv_utils(void) @@ -296,6 +357,7 @@ static void exit_hyperv_utils(void) kfree(shut_txf_buf); kfree(time_txf_buf); kfree(hbeat_txf_buf); + vmbus_child_driver_unregister(&util_drv.driver); } module_init(init_hyperv_utils); -- cgit v1.1 From c45cf2d4976e2fcde68d88898a37af70f2caaf5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 11:41:33 -0700 Subject: Staging: hv: create VMBUS_DEVICE macro and use it. This is to be used to be able to write hv_vmbus_device_id tables easier. This patch also converts all hv drivers to use the macro, saving some lines of code and making things easier to read overall. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 14 ++++--------- drivers/staging/hv/hv_mouse.c | 14 ++++--------- drivers/staging/hv/hv_util.c | 44 ++++++++++++---------------------------- drivers/staging/hv/hyperv.h | 11 ++++++++++ drivers/staging/hv/netvsc_drv.c | 14 ++++--------- drivers/staging/hv/storvsc_drv.c | 14 ++++--------- 6 files changed, 40 insertions(+), 71 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 9b99387..d170f24 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -795,16 +795,10 @@ static void blkvsc_request(struct request_queue *queue) } static const struct hv_vmbus_device_id id_table[] = { - { - /* IDE guid */ - .guid = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } - }, - { - .guid = { } - }, + /* IDE guid */ + { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index dd8a114..ebd1715 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -909,16 +909,10 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Mouse guid */ - .guid = { - 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, - 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A - } - }, - { - .guid = { } - }, + /* Mouse guid */ + { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, + 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, + { }, }; /* diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index a620f4d..5bd6f00 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -227,37 +227,19 @@ static int util_remove(struct hv_device *dev) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Shutdown guid */ - .guid = { - 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB - } - }, - { - /* Time synch guid */ - .guid = { - 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf - } - }, - { - /* Heartbeat guid */ - .guid = { - 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d - } - }, - { - /* KVP guid */ - .guid = { - 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 - } - }, - { - .guid = { } - }, + /* Shutdown guid */ + { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) }, + /* Time synch guid */ + { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, + 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) }, + /* Heartbeat guid */ + { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) }, + /* KVP guid */ + { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, + 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index b8199f4..d96de66 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -848,6 +848,17 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) int vmbus_child_driver_register(struct device_driver *drv); void vmbus_child_driver_unregister(struct device_driver *drv); +/** + * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device + * + * This macro is used to create a struct hv_vmbus_device_id that matches a + * specific device. + */ +#define VMBUS_DEVICE(g0, g1, g2, g3, g4, g5, g6, g7, \ + g8, g9, ga, gb, gc, gd, ge, gf) \ + .guid = { g0, g1, g2, g3, g4, g5, g6, g7, \ + g8, g9, ga, gb, gc, gd, ge, gf }, + /* * Common header for Hyper-V ICs */ diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 2e25c95..c3b7de1 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -414,16 +414,10 @@ static int netvsc_remove(struct hv_device *dev) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Network guid */ - .guid = { - 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E - } - }, - { - .guid = { } - }, + /* Network guid */ + { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, + 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ed2140c..f85f2ea 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -639,16 +639,10 @@ static struct scsi_host_template scsi_driver = { }; static const struct hv_vmbus_device_id id_table[] = { - { - /* SCSI guid */ - .guid = { - 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f - } - }, - { - .guid = { } - }, + /* SCSI guid */ + { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, + 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); -- cgit v1.1 From 5cee7cb79d210f48c19692a79e0508ec001e439f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:37 -0700 Subject: Staging: hv: vmbus: Cleanup vmbus_match() Use the preferred mechanism to compare guids in vmbus_match(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c88a183..b651968 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -302,8 +302,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver) struct hv_device *hv_dev = device_to_hv_device(device); /* We found our driver ? */ - if (memcmp(&hv_dev->dev_type, &drv->dev_type, - sizeof(uuid_le)) == 0) + if (!uuid_le_cmp(hv_dev->dev_type, drv->dev_type)) match = 1; return match; -- cgit v1.1 From 0ddda6603a6eea0b3aff294648ecb30a22e974f1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:38 -0700 Subject: Staging: hv: vmbus: Cleanup vmbus_uevent() code Now generate appropriate uevent based on the modalias string. As part of this, cleanup the existing uevent code. [gregkh - fixed code to handle driver_data portion of struct hv_vmbus_device_id] Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 56 ++++++++---------------------------------- 1 file changed, 10 insertions(+), 46 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index b651968..afb16704 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -237,58 +237,22 @@ static struct device_attribute vmbus_device_attrs[] = { * This routine is invoked when a device is added or removed on the vmbus to * generate a uevent to udev in the userspace. The udev will then look at its * rule and the uevent generated here to load the appropriate driver + * + * The alias string will be of the form vmbus:guid where guid is the string + * representation of the device guid (each byte of the guid will be + * represented with two hex characters. */ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) { struct hv_device *dev = device_to_hv_device(device); - int ret; - - ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={" - "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x%02x%02x}", - dev->dev_type.b[3], - dev->dev_type.b[2], - dev->dev_type.b[1], - dev->dev_type.b[0], - dev->dev_type.b[5], - dev->dev_type.b[4], - dev->dev_type.b[7], - dev->dev_type.b[6], - dev->dev_type.b[8], - dev->dev_type.b[9], - dev->dev_type.b[10], - dev->dev_type.b[11], - dev->dev_type.b[12], - dev->dev_type.b[13], - dev->dev_type.b[14], - dev->dev_type.b[15]); - - if (ret) - return ret; + int i, ret; + char alias_name[((sizeof((struct hv_vmbus_device_id *)0)->guid) + 1) * 2]; - ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={" - "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x%02x%02x}", - dev->dev_instance.b[3], - dev->dev_instance.b[2], - dev->dev_instance.b[1], - dev->dev_instance.b[0], - dev->dev_instance.b[5], - dev->dev_instance.b[4], - dev->dev_instance.b[7], - dev->dev_instance.b[6], - dev->dev_instance.b[8], - dev->dev_instance.b[9], - dev->dev_instance.b[10], - dev->dev_instance.b[11], - dev->dev_instance.b[12], - dev->dev_instance.b[13], - dev->dev_instance.b[14], - dev->dev_instance.b[15]); - if (ret) - return ret; + for (i = 0; i < ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2); i += 2) + sprintf(&alias_name[i], "%02x", dev->dev_type.b[i/2]); - return 0; + ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name); + return ret; } -- cgit v1.1 From 5841a829594983077f670192b78fee4f7712e2b4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:39 -0700 Subject: Staging: hv: vmbus: Support the notion of id tables in vmbus_match() Introduce code to handle driver specific id tables to the vmbus core (vmbus_match). This would allow us to handle more than one device type with a given driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index afb16704..82769a4 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -255,21 +255,31 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) return ret; } +static uuid_le null_guid; + +static inline bool is_null_guid(const __u8 *guid) +{ + if (memcmp(guid, &null_guid, sizeof(uuid_le))) + return false; + return true; +} + /* * vmbus_match - Attempt to match the specified device to the specified driver */ static int vmbus_match(struct device *device, struct device_driver *driver) { - int match = 0; struct hv_driver *drv = drv_to_hv_drv(driver); struct hv_device *hv_dev = device_to_hv_device(device); + const struct hv_vmbus_device_id *id_array = drv->id_table; - /* We found our driver ? */ - if (!uuid_le_cmp(hv_dev->dev_type, drv->dev_type)) - match = 1; + for (; !is_null_guid(id_array->guid); id_array++) + if (!memcmp(&id_array->guid, &hv_dev->dev_type.b, + sizeof(struct hv_vmbus_device_id))) + return 1; - return match; + return 0; } /* -- cgit v1.1 From 49ce6757cfb4de5be695a47f2cbcbc5589838af6 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:40 -0700 Subject: Staging: hv: vmbus: Get rid of an unnecessary include line in vmbus_drv.c Get rid of an unnecessary include line in vmbus_drv.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 82769a4..0114b04 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From 4e80fbfc7ff4e063d96b258aaa3da97e8e4dc6a5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:41 -0700 Subject: Staging: hv: storvsc: Get rid of the DMI signature Now that we have implemented a vmbus specific mechanism for auto-loading, get rid of the DMI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index f85f2ea..6f67e9b 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -724,27 +723,6 @@ static struct hv_driver storvsc_drv = { .remove = storvsc_remove, }; -/* - * We use a DMI table to determine if we should autoload this driver This is - * needed by distro tools to determine if the hyperv drivers should be - * installed and/or configured. We don't do anything else with the table, but - * it needs to be present. - */ - -static const struct dmi_system_id __initconst -hv_stor_dmi_table[] __maybe_unused = { - { - .ident = "Hyper-V", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), - DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), - }, - }, - { }, -}; -MODULE_DEVICE_TABLE(dmi, hv_stor_dmi_table); - static int __init storvsc_drv_init(void) { int ret; -- cgit v1.1 From d7dc6b9c2e8fec9f9d6ebe518918d028a505ef7b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:42 -0700 Subject: Staging: hv: netvsc: Get rid of the PCI signature Now that we have implemented a vmbus specific mechanism for auto-loading, get rid of the PCI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index c3b7de1..1c3c5fe 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -471,13 +470,6 @@ static int __init netvsc_drv_init(void) return ret; } -static const struct pci_device_id __initconst -hv_netvsc_pci_table[] __maybe_unused = { - { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, hv_netvsc_pci_table); - MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); -- cgit v1.1 From 2e7a35adbb4fdca2e5f2a02791c83704f4b1797f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:43 -0700 Subject: Staging: hv: netvsc: Get rid of the DMI signature in netvsc_drv.c Now that we have implemented a vmbus specific mechanism for auto-loading, get rid of the DMI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 1c3c5fe..2d2955c1 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -434,20 +433,6 @@ static void __exit netvsc_drv_exit(void) } -static const struct dmi_system_id __initconst -hv_netvsc_dmi_table[] __maybe_unused = { - { - .ident = "Hyper-V", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), - DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), - }, - }, - { }, -}; -MODULE_DEVICE_TABLE(dmi, hv_netvsc_dmi_table); - static int __init netvsc_drv_init(void) { struct hv_driver *drv = &netvsc_drv; @@ -455,10 +440,6 @@ static int __init netvsc_drv_init(void) pr_info("initializing...."); - if (!dmi_check_system(hv_netvsc_dmi_table)) - return -ENODEV; - - /* Callback to client driver to complete the initialization */ netvsc_initialize(drv); -- cgit v1.1 From 84385b057fae74eb91a2a163be59543a31291bc6 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:44 -0700 Subject: Staging: hv: util: Get rid of the DMI signature in hv_util.c Now that we have implemented a vmbus specific mechanism for auto-loading, get rid of the DMI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index 5bd6f00..c16a7f1 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "hyperv.h" @@ -258,22 +257,6 @@ hv_utils_pci_table[] __maybe_unused = { }; MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); - -static const struct dmi_system_id __initconst -hv_utils_dmi_table[] __maybe_unused = { - { - .ident = "Hyper-V", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), - DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), - }, - }, - { }, -}; -MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table); - - static int __init init_hyperv_utils(void) { pr_info("Registering HyperV Utility Driver\n"); @@ -282,9 +265,6 @@ static int __init init_hyperv_utils(void) return -ENODEV; - if (!dmi_check_system(hv_utils_dmi_table)) - return -ENODEV; - shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -- cgit v1.1 From c411a5981d6f53ed2502ad06a2ee70d67ed13f12 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:45 -0700 Subject: Staging: hv: util: Get rid of the PCI signature in hv_util.c Now that we have implemented a vmbus specific mechanism for auto-loading, get rid of the PCI signature. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index c16a7f1..b0d89de 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "hyperv.h" #include "hv_kvp.h" @@ -250,13 +249,6 @@ static struct hv_driver util_drv = { .remove = util_remove, }; -static const struct pci_device_id __initconst -hv_utils_pci_table[] __maybe_unused = { - { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); - static int __init init_hyperv_utils(void) { pr_info("Registering HyperV Utility Driver\n"); -- cgit v1.1 From 768fa21919b7f30b77f0b3ba94939f5556d111d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 15:07:32 -0700 Subject: Staging: hv: fix up driver registering mess Individual drivers should never be touching the 'struct device' field, so if that is a requirement to pass to the vmbus core, you know something is wrong. This patch fixes that all up, and resolves the problem where the module reference counting was not happening properly for the individual drivers as well. Overall, it reduces the lines of code the individual drivers have to have, which tells you that this is the correct thing to do. Also, somehow the _GPL marking for the functions got removed on an older patch. As the name of the function was changing, properly change the _GPL marking as well at the same time. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 17 +++------------- drivers/staging/hv/hv_mouse.c | 21 +++----------------- drivers/staging/hv/hv_util.c | 9 +++------ drivers/staging/hv/hyperv.h | 8 ++++++-- drivers/staging/hv/hyperv_net.h | 1 - drivers/staging/hv/netvsc.c | 14 ------------- drivers/staging/hv/netvsc_drv.c | 19 +++--------------- drivers/staging/hv/storvsc_drv.c | 24 +++++++--------------- drivers/staging/hv/vmbus_drv.c | 43 ++++++++++++++++++++-------------------- 9 files changed, 46 insertions(+), 110 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index d170f24..07dc9ed 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -109,7 +109,6 @@ struct block_device_context { int users; }; -static const char *drv_name = "blkvsc"; /* * There is a circular dependency involving blkvsc_request_completion() @@ -805,6 +804,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver blkvsc_drv = { + .name = "blkvsc", .id_table = id_table, .probe = blkvsc_probe, .remove = blkvsc_remove, @@ -824,24 +824,13 @@ static const struct block_device_operations block_ops = { */ static int blkvsc_drv_init(void) { - struct hv_driver *drv = &blkvsc_drv; - int ret; - BUILD_BUG_ON(sizeof(sector_t) != 8); - - drv->driver.name = drv_name; - - /* The driver belongs to vmbus */ - ret = vmbus_child_driver_register(&drv->driver); - - return ret; + return vmbus_driver_register(&blkvsc_drv); } - static void blkvsc_drv_exit(void) { - - vmbus_child_driver_unregister(&blkvsc_drv.driver); + vmbus_driver_unregister(&blkvsc_drv); } /* diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index ebd1715..5727173 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -176,8 +176,6 @@ struct mousevsc_dev { }; -static const char *driver_name = "mousevsc"; - static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info); static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); @@ -921,33 +919,20 @@ static const struct hv_vmbus_device_id id_table[] = { /* MODULE_DEVICE_TABLE(vmbus, id_table); */ static struct hv_driver mousevsc_drv = { + .name = "mousevsc", .id_table = id_table, .probe = mousevsc_probe, .remove = mousevsc_remove, }; -static void mousevsc_drv_exit(void) -{ - vmbus_child_driver_unregister(&mousevsc_drv.driver); -} - static int __init mousevsc_init(void) { - struct hv_driver *drv = &mousevsc_drv; - - DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing."); - - drv->driver.name = driver_name; - - /* The driver belongs to vmbus */ - vmbus_child_driver_register(&drv->driver); - - return 0; + return vmbus_driver_register(&mousevsc_drv); } static void __exit mousevsc_exit(void) { - mousevsc_drv_exit(); + vmbus_driver_unregister(&mousevsc_drv); } /* diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index b0d89de..f2f456f 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -34,8 +34,6 @@ static u8 *shut_txf_buf; static u8 *time_txf_buf; static u8 *hbeat_txf_buf; -static const char *driver_name = "hv_util"; - static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; @@ -244,6 +242,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver util_drv = { + .name = "hv_util", .id_table = id_table, .probe = util_probe, .remove = util_remove, @@ -277,9 +276,7 @@ static int __init init_hyperv_utils(void) hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; - util_drv.driver.name = driver_name; - - return vmbus_child_driver_register(&util_drv.driver); + return vmbus_driver_register(&util_drv); } static void exit_hyperv_utils(void) @@ -311,7 +308,7 @@ static void exit_hyperv_utils(void) kfree(shut_txf_buf); kfree(time_txf_buf); kfree(hbeat_txf_buf); - vmbus_child_driver_unregister(&util_drv.driver); + vmbus_driver_unregister(&util_drv); } module_init(init_hyperv_utils); diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index d96de66..c249811 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -845,8 +845,12 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) /* Vmbus interface */ -int vmbus_child_driver_register(struct device_driver *drv); -void vmbus_child_driver_unregister(struct device_driver *drv); +#define vmbus_driver_register(driver) \ + __vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +int __must_check __vmbus_driver_register(struct hv_driver *hv_driver, + struct module *owner, + const char *mod_name); +void vmbus_driver_unregister(struct hv_driver *hv_driver); /** * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index 27f987b..5782fea 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -96,7 +96,6 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet); -int netvsc_initialize(struct hv_driver *drv); int rndis_filter_open(struct hv_device *dev); int rndis_filter_close(struct hv_device *dev); int rndis_filter_device_add(struct hv_device *dev, diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 6f4541b..cb02eed 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -32,9 +32,6 @@ #include "hyperv_net.h" -/* Globals */ -static const char *driver_name = "netvsc"; - static struct netvsc_device *alloc_net_device(struct hv_device *device) { struct netvsc_device *net_device; @@ -992,14 +989,3 @@ cleanup: return ret; } - -/* - * netvsc_initialize - Main entry point - */ -int netvsc_initialize(struct hv_driver *drv) -{ - - drv->name = driver_name; - - return 0; -} diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 2d2955c1..ad1ef03 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -422,6 +422,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver netvsc_drv = { + .name = "netvsc", .id_table = id_table, .probe = netvsc_probe, .remove = netvsc_remove, @@ -429,26 +430,12 @@ static struct hv_driver netvsc_drv = { static void __exit netvsc_drv_exit(void) { - vmbus_child_driver_unregister(&netvsc_drv.driver); + vmbus_driver_unregister(&netvsc_drv); } - static int __init netvsc_drv_init(void) { - struct hv_driver *drv = &netvsc_drv; - int ret; - - pr_info("initializing...."); - - /* Callback to client driver to complete the initialization */ - netvsc_initialize(drv); - - drv->driver.name = drv->name; - - /* The driver belongs to vmbus */ - ret = vmbus_child_driver_register(&drv->driver); - - return ret; + return vmbus_driver_register(&netvsc_drv); } MODULE_LICENSE("GPL"); diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 6f67e9b..0297418 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -41,8 +41,6 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); -static const char *driver_name = "storvsc"; - struct hv_host_device { struct hv_device *dev; struct kmem_cache *request_pool; @@ -718,6 +716,7 @@ static int storvsc_probe(struct hv_device *device) /* The one and only one */ static struct hv_driver storvsc_drv = { + .name = "storvsc", .id_table = id_table, .probe = storvsc_probe, .remove = storvsc_remove, @@ -725,8 +724,6 @@ static struct hv_driver storvsc_drv = { static int __init storvsc_drv_init(void) { - int ret; - struct hv_driver *drv = &storvsc_drv; u32 max_outstanding_req_per_channel; /* @@ -735,29 +732,22 @@ static int __init storvsc_drv_init(void) * the ring buffer indices) by the max request size (which is * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64) */ - max_outstanding_req_per_channel = - ((storvsc_ringbuffer_size - PAGE_SIZE) / - ALIGN(MAX_MULTIPAGE_BUFFER_PACKET + - sizeof(struct vstor_packet) + sizeof(u64), - sizeof(u64))); + ((storvsc_ringbuffer_size - PAGE_SIZE) / + ALIGN(MAX_MULTIPAGE_BUFFER_PACKET + + sizeof(struct vstor_packet) + sizeof(u64), + sizeof(u64))); if (max_outstanding_req_per_channel < STORVSC_MAX_IO_REQUESTS) return -1; - drv->driver.name = driver_name; - - - /* The driver belongs to vmbus */ - ret = vmbus_child_driver_register(&drv->driver); - - return ret; + return vmbus_driver_register(&storvsc_drv); } static void __exit storvsc_drv_exit(void) { - vmbus_child_driver_unregister(&storvsc_drv.driver); + vmbus_driver_unregister(&storvsc_drv); } MODULE_LICENSE("GPL"); diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 0114b04..26f4901 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -552,51 +552,50 @@ static int vmbus_bus_init(int irq) } /** - * vmbus_child_driver_register() - Register a vmbus's child driver - * @drv: Pointer to driver structure you want to register - * + * __vmbus_child_driver_register - Register a vmbus's driver + * @drv: Pointer to driver structure you want to register + * @owner: owner module of the drv + * @mod_name: module name string * * Registers the given driver with Linux through the 'driver_register()' call - * And sets up the hyper-v vmbus handling for this driver. + * and sets up the hyper-v vmbus handling for this driver. * It will return the state of the 'driver_register()' call. * - * Mainly used by Hyper-V drivers. */ -int vmbus_child_driver_register(struct device_driver *drv) +int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name) { int ret; - pr_info("child driver registering - name %s\n", drv->name); + pr_info("registering driver %s\n", hv_driver->name); - /* The child driver on this vmbus */ - drv->bus = &hv_bus; + hv_driver->driver.name = hv_driver->name; + hv_driver->driver.owner = owner; + hv_driver->driver.mod_name = mod_name; + hv_driver->driver.bus = &hv_bus; - ret = driver_register(drv); + ret = driver_register(&hv_driver->driver); vmbus_request_offers(); return ret; } -EXPORT_SYMBOL(vmbus_child_driver_register); +EXPORT_SYMBOL_GPL(__vmbus_driver_register); /** - * vmbus_child_driver_unregister() - Unregister a vmbus's child driver - * @drv: Pointer to driver structure you want to un-register - * - * - * Un-register the given driver with Linux through the 'driver_unregister()' - * call. And ungegisters the driver from the Hyper-V vmbus handler. + * vmbus_driver_unregister() - Unregister a vmbus's driver + * @drv: Pointer to driver structure you want to un-register * - * Mainly used by Hyper-V drivers. + * Un-register the given driver that was previous registered with a call to + * vmbus_driver_register() */ -void vmbus_child_driver_unregister(struct device_driver *drv) +void vmbus_driver_unregister(struct hv_driver *hv_driver) { - pr_info("child driver unregistering - name %s\n", drv->name); + pr_info("unregistering driver %s\n", hv_driver->name); - driver_unregister(drv); + driver_unregister(&hv_driver->driver); } -EXPORT_SYMBOL(vmbus_child_driver_unregister); +EXPORT_SYMBOL_GPL(vmbus_driver_unregister); /* * vmbus_child_device_create - Creates and registers a new child device -- cgit v1.1 From 94a66c9c803a31805d98c92e65593b756ffa05c4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:49 -0700 Subject: Staging: hv: vmbus: Get rid of some unnecessary comments Get rid of some unnecessary comments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 26f4901..be62b62 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -44,8 +44,6 @@ static struct tasklet_struct event_dpc; unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL); EXPORT_SYMBOL(vmbus_loglevel); - /* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */ - /* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */ static struct completion probe_event; static int irq; -- cgit v1.1 From ffca7c40b62b182d9de17c7229346f4230df46d6 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:50 -0700 Subject: Staging: hv: vmbus: Cleanup unnecessary comments in hv.c Cleanup unnecessary comments in hv.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c index 2192d78..d2b921b 100644 --- a/drivers/staging/hv/hv.c +++ b/drivers/staging/hv/hv.c @@ -164,11 +164,7 @@ int hv_init(void) goto cleanup; max_leaf = query_hypervisor_info(); - /* HvQueryHypervisorFeatures(maxLeaf); */ - /* - * We only support running on top of Hyper-V - */ rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); if (hv_context.guestid != 0) @@ -181,10 +177,6 @@ int hv_init(void) /* See if the hypercall page is already set */ rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - /* - * Allocate the hypercall page memory - * virtaddr = osd_page_alloc(1); - */ virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); if (!virtaddr) -- cgit v1.1 From 5433e00334d3e20f8bff70845c7f44e00cdf2d14 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:51 -0700 Subject: Staging: hv: vmbus: Cleanup error handling in hv_init() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c index d2b921b..736794e 100644 --- a/drivers/staging/hv/hv.c +++ b/drivers/staging/hv/hv.c @@ -151,7 +151,6 @@ static u64 do_hypercall(u64 control, void *input, void *output) */ int hv_init(void) { - int ret = 0; int max_leaf; union hv_x64_msr_hypercall_contents hypercall_msr; void *virtaddr = NULL; @@ -214,7 +213,7 @@ int hv_init(void) hv_context.signal_event_param->flag_number = 0; hv_context.signal_event_param->rsvdz = 0; - return ret; + return 0; cleanup: if (virtaddr) { @@ -225,8 +224,8 @@ cleanup: vfree(virtaddr); } - ret = -1; - return ret; + + return -ENOTSUPP; } /* -- cgit v1.1 From 7a9462d842197cba9ca16b915284289535c88675 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:52 -0700 Subject: Staging: hv: vmbus: Get rid of unnecessay comments in connection.c Get rid of unnecessay comments in connection.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index e6b4039..0e7efce 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -215,8 +215,6 @@ static void process_chn_event(u32 relid) { struct vmbus_channel *channel; - /* ASSERT(relId > 0); */ - /* * Find the channel based on this relid and invokes the * channel callback to process the event -- cgit v1.1 From 1f22b9aae313ae5707358abbe9617ea13c7f80c5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:53 -0700 Subject: Staging: hv: vmbus: Get rid of the function dump_gpadl_body() Get rid of the function dump_gpadl_body() since it adds no value and actually is in the data path. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index 222adcc..2d5bfac 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -239,24 +239,6 @@ errorout: } EXPORT_SYMBOL_GPL(vmbus_open); -/* - * dump_gpadl_body - Dump the gpadl body message to the console for - * debugging purposes. - */ -static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len) -{ - int i; - int pfncount; - - pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) / - sizeof(u64); - - DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount); - - for (i = 0; i < pfncount; i++) - DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu", - i, gpadl->pfn[i]); -} /* * dump_gpadl_header - Dump the gpadl header message to the console for @@ -485,8 +467,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, CHANNELMSG_GPADL_BODY; gpadl_body->gpadl = next_gpadl_handle; - dump_gpadl_body(gpadl_body, submsginfo->msgsize - - sizeof(*submsginfo)); ret = vmbus_post_msg(gpadl_body, submsginfo->msgsize - sizeof(*submsginfo)); -- cgit v1.1 From da06da287d9f2697f247024efbb6e18a764411f8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:54 -0700 Subject: Staging: hv: vmbus: Get rid of the function dump_gpadl_header() Get rid of the function dump_gpadl_header() as this adds no value. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index 2d5bfac..aa0a150 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -239,33 +239,6 @@ errorout: } EXPORT_SYMBOL_GPL(vmbus_open); - -/* - * dump_gpadl_header - Dump the gpadl header message to the console for - * debugging purposes. - */ -static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl) -{ - int i, j; - int pagecount; - - DPRINT_DBG(VMBUS, - "gpadl header - relid %d, range count %d, range buflen %d", - gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen); - for (i = 0; i < gpadl->rangecount; i++) { - pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT; - pagecount = (pagecount > 26) ? 26 : pagecount; - - DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d " - "page count %d", i, gpadl->range[i].byte_count, - gpadl->range[i].byte_offset, pagecount); - - for (j = 0; j < pagecount; j++) - DPRINT_DBG(VMBUS, "%d) pfn %llu", j, - gpadl->range[i].pfn_array[j]); - } -} - /* * create_gpadl_header - Creates a gpadl for the specified buffer */ @@ -443,7 +416,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, gpadlmsg->child_relid = channel->offermsg.child_relid; gpadlmsg->gpadl = next_gpadl_handle; - dump_gpadl_header(gpadlmsg); spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_add_tail(&msginfo->msglistentry, -- cgit v1.1 From 0987ff696d55ad4454211d0b72615fb52b05aa77 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:55 -0700 Subject: Staging: hv: vmbus: Rename openMsg to open_msg in channel.c Rename openMsg to open_msg in channel.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index aa0a150..ebd7552 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -119,7 +119,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, u32 recv_ringbuffer_size, void *userdata, u32 userdatalen, void (*onchannelcallback)(void *context), void *context) { - struct vmbus_channel_open_channel *openMsg; + struct vmbus_channel_open_channel *open_msg; struct vmbus_channel_msginfo *openInfo = NULL; void *in, *out; unsigned long flags; @@ -183,14 +183,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, init_completion(&openInfo->waitevent); - openMsg = (struct vmbus_channel_open_channel *)openInfo->msg; - openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL; - openMsg->openid = newchannel->offermsg.child_relid; - openMsg->child_relid = newchannel->offermsg.child_relid; - openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle; - openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >> + open_msg = (struct vmbus_channel_open_channel *)openInfo->msg; + open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL; + open_msg->openid = newchannel->offermsg.child_relid; + open_msg->child_relid = newchannel->offermsg.child_relid; + open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle; + open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >> PAGE_SHIFT; - openMsg->server_contextarea_gpadlhandle = 0; + open_msg->server_contextarea_gpadlhandle = 0; if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; @@ -198,14 +198,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, } if (userdatalen) - memcpy(openMsg->userdata, userdata, userdatalen); + memcpy(open_msg->userdata, userdata, userdatalen); spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_add_tail(&openInfo->msglistentry, &vmbus_connection.chn_msg_list); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - ret = vmbus_post_msg(openMsg, + ret = vmbus_post_msg(open_msg, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) -- cgit v1.1 From c8a56985faae8e4150779b781de8d53afa4a7da2 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:56 -0700 Subject: Staging: hv: vmbus: Get rid of unnecessary comments in channel.c Get rid of unnecessary comments in channel.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index ebd7552..e02060e 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -76,7 +76,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, struct hv_monitor_page *monitorpage; u8 monitor_group = (u8)channel->offermsg.monitorid / 32; u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - /* u32 monitorBit = 1 << monitorOffset; */ debuginfo->relid = channel->offermsg.child_relid; debuginfo->state = channel->state; @@ -392,7 +391,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, { struct vmbus_channel_gpadl_header *gpadlmsg; struct vmbus_channel_gpadl_body *gpadl_body; - /* struct vmbus_channel_gpadl_created *gpadlCreated; */ struct vmbus_channel_msginfo *msginfo = NULL; struct vmbus_channel_msginfo *submsginfo; u32 msgcount; @@ -474,8 +472,6 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) unsigned long flags; int ret, t; - /* ASSERT(gpadl_handle != 0); */ - info = kmalloc(sizeof(*info) + sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); if (!info) -- cgit v1.1 From 176fb9e3f1c145c502dfcd88b2800039aa5e2a24 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:57 -0700 Subject: Staging: hv: vmbus: Change the variable name openInfo to open_info in channel.c Change the variable name openInfo to open_info in channel.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index e02060e..9eb8def 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -119,7 +119,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, void (*onchannelcallback)(void *context), void *context) { struct vmbus_channel_open_channel *open_msg; - struct vmbus_channel_msginfo *openInfo = NULL; + struct vmbus_channel_msginfo *open_info = NULL; void *in, *out; unsigned long flags; int ret, t, err = 0; @@ -172,17 +172,17 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, } /* Create and init the channel open message */ - openInfo = kmalloc(sizeof(*openInfo) + + open_info = kmalloc(sizeof(*open_info) + sizeof(struct vmbus_channel_open_channel), GFP_KERNEL); - if (!openInfo) { + if (!open_info) { err = -ENOMEM; goto errorout; } - init_completion(&openInfo->waitevent); + init_completion(&open_info->waitevent); - open_msg = (struct vmbus_channel_open_channel *)openInfo->msg; + open_msg = (struct vmbus_channel_open_channel *)open_info->msg; open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL; open_msg->openid = newchannel->offermsg.child_relid; open_msg->child_relid = newchannel->offermsg.child_relid; @@ -200,7 +200,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, memcpy(open_msg->userdata, userdata, userdatalen); spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_add_tail(&openInfo->msglistentry, + list_add_tail(&open_info->msglistentry, &vmbus_connection.chn_msg_list); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -210,22 +210,22 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) goto cleanup; - t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ); + t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; goto errorout; } - if (openInfo->response.open_result.status) - err = openInfo->response.open_result.status; + if (open_info->response.open_result.status) + err = open_info->response.open_result.status; cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&openInfo->msglistentry); + list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - kfree(openInfo); + kfree(open_info); return err; errorout: @@ -233,7 +233,7 @@ errorout: hv_ringbuffer_cleanup(&newchannel->inbound); free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); - kfree(openInfo); + kfree(open_info); return err; } EXPORT_SYMBOL_GPL(vmbus_open); -- cgit v1.1 From d2598f017f02bbc3623503c6e08f22f7ea473cdd Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:58 -0700 Subject: Staging: hv: vmbus: Cleanup error values in ringbuffer.c Use standard Linux errno values in ringbuffer.c and do the associated cleanup in the clients. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 2 +- drivers/staging/hv/netvsc.c | 2 +- drivers/staging/hv/ring_buffer.c | 6 +++--- drivers/staging/hv/storvsc_drv.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 07dc9ed..2b41eb6 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -725,7 +725,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, } else { ret = blkvsc_submit_request(blkvsc_req, blkvsc_request_completion); - if (ret == -1) { + if (ret == -EAGAIN) { pending = 1; list_add_tail(&blkvsc_req->pend_entry, &blkdev->pending_list); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index cb02eed..d547ff6 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -565,7 +565,7 @@ retry_send_cmplt: if (ret == 0) { /* success */ /* no-op */ - } else if (ret == -1) { + } else if (ret == -EAGAIN) { /* no more room...wait a bit and attempt to retry 3 times */ retries++; dev_err(&device->device, "unable to send receive completion pkt" diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index 42f7672..9212699 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -390,7 +390,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, /* is empty since the read index == write index */ if (bytes_avail_towrite <= totalbytes_towrite) { spin_unlock_irqrestore(&outring_info->ring_lock, flags); - return -1; + return -EAGAIN; } /* Write to the ring buffer */ @@ -450,7 +450,7 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info, spin_unlock_irqrestore(&Inring_info->ring_lock, flags); - return -1; + return -EAGAIN; } /* Convert to byte offset */ @@ -496,7 +496,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, if (bytes_avail_toread < buflen) { spin_unlock_irqrestore(&inring_info->ring_lock, flags); - return -1; + return -EAGAIN; } next_read_location = diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 0297418..29ac644 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -578,7 +578,7 @@ retry_request: /* Invokes the vsc to start an IO */ ret = storvsc_do_io(dev, &cmd_request->request); - if (ret == -1) { + if (ret == -EAGAIN) { /* no more space */ if (cmd_request->bounce_sgl_count) { -- cgit v1.1 From 3d5cad97c4be2bfc5cb4e52a0972c6e3bf8c278d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:59 -0700 Subject: Staging: hv: vmbus: Cleanup the error return value in vmbus_recvpacket_raw() Use standard Linux errno values. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 2 +- drivers/staging/hv/hv_mouse.c | 2 +- drivers/staging/hv/netvsc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index 9eb8def..ac92c1f 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -811,7 +811,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, pr_err("Buffer too small - needed %d bytes but " "got space for only %d bytes\n", packetlen, bufferlen); - return -2; + return -ENOBUFS; } *requestid = desc.trans_id; diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 5727173..d7e24bc 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -539,7 +539,7 @@ static void mousevsc_on_channel_callback(void *context) } break; } - } else if (ret == -2) { + } else if (ret == -ENOBUFS) { /* Handle large packet */ bufferlen = bytes_recvd; buffer = kzalloc(bytes_recvd, GFP_KERNEL); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index d547ff6..b89ac7e 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -884,7 +884,7 @@ static void netvsc_channel_cb(void *context) break; } - } else if (ret == -2) { + } else if (ret == -ENOBUFS) { /* Handle large packet */ buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { -- cgit v1.1 From 0293e5cabcd9067f35a64575922470b92d642d0e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:00 -0700 Subject: Staging: hv: netvsc: Get rid of an unnecessary print statement in netvsc_probe() Get rid of an unnecessary print statement in netvsc_probe(). Furthermore, this fixes a bug since netdev_err is being invoked after the device has been freed. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index ad1ef03..0b8ac1a 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -355,8 +355,6 @@ static int netvsc_probe(struct hv_device *dev) if (ret != 0) { free_netdev(net); dev_set_drvdata(&dev->device, NULL); - - netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); return ret; } -- cgit v1.1 From 5289d3d160e8d5c63974502696ab5def71891f18 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:01 -0700 Subject: Staging: hv: vmbus: Retry vmbus_post_msg() before giving up The function hv_post_msg() can fail because of transient resource conditions. It may be useful to retry the operation. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index 0e7efce..a88ad70 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -268,10 +269,25 @@ void vmbus_on_event(unsigned long data) int vmbus_post_msg(void *buffer, size_t buflen) { union hv_connection_id conn_id; + int ret = 0; + int retries = 0; conn_id.asu32 = 0; conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; - return hv_post_message(conn_id, 1, buffer, buflen); + + /* + * hv_post_message() can have transient failures because of + * insufficient resources. Retry the operation a couple of + * times before giving up. + */ + while (retries < 3) { + ret = hv_post_message(conn_id, 1, buffer, buflen); + if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) + return ret; + retries++; + msleep(100); + } + return ret; } /* -- cgit v1.1 From d225d36b13927defee0f5d51ade9987bb617d465 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:02 -0700 Subject: Staging: hv: storvsc: Cleanup error handling in storvsc_dev_add() Use standard Linux error values and cleanup error handling. I would like to acknowledge Andre Bartke (andre.bartke@gmail.com) for highlighting this problem. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 3029786..915aeee 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -392,10 +392,8 @@ int storvsc_dev_add(struct hv_device *device, device_info = (struct storvsc_device_info *)additional_info; stor_device = alloc_stor_device(device); - if (!stor_device) { - ret = -1; - goto cleanup; - } + if (!stor_device) + return -ENOMEM; /* Save the channel properties to our storvsc channel */ @@ -409,11 +407,13 @@ int storvsc_dev_add(struct hv_device *device, stor_device->port_number = device_info->port_number; /* Send it back up */ ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size); - + if (ret) { + free_stor_device(stor_device); + return ret; + } device_info->path_id = stor_device->path_id; device_info->target_id = stor_device->target_id; -cleanup: return ret; } -- cgit v1.1 From 5260e291ff116ff1db14166a778fcab3f5932bc8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:03 -0700 Subject: Staging: hv: storvsc: Cleanup error handling in storvsc_channel_init() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 915aeee..22ac6f2 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -111,7 +111,7 @@ static int storvsc_channel_init(struct hv_device *device) stor_device = get_stor_device(device); if (!stor_device) - return -1; + return -ENODEV; request = &stor_device->init_request; vstor_packet = &request->vstor_packet; -- cgit v1.1 From cae50a27a0405b7a70a97a2c9c22912955c84d44 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:04 -0700 Subject: Staging: hv: storvsc: Cleanup error handling in storvsc_connect_to_vsp() Cleanup error handling in storvsc_connect_to_vsp(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 22ac6f2..2b73f72 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -376,7 +376,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) storvsc_on_channel_callback, device); if (ret != 0) - return -1; + return ret; ret = storvsc_channel_init(device); -- cgit v1.1 From 3b54eed7de90d59b2c6fa416513826279acc3bbd Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:05 -0700 Subject: Staging: hv: storvsc: Cleanup error handling in storvsc_do_io() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 2b73f72..2b914e4 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -454,7 +454,7 @@ int storvsc_do_io(struct hv_device *device, stor_device = get_stor_device(device); if (!stor_device) - return -2; + return -ENODEV; request->device = device; -- cgit v1.1 From e9bda4348b8dc907ffb26dcda53fff568d35a045 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:06 -0700 Subject: Storage: hv: storvsc: Get rid of some unnecessary DPRINTs from storvsc.c Get rid of some unnecessary DPRINTs from storvsc.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 2b914e4..3730f3f 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -125,8 +125,6 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION..."); - ret = vmbus_sendpacket(device->channel, vstor_packet, sizeof(struct vstor_packet), (unsigned long)request, @@ -145,7 +143,6 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->status != 0) goto cleanup; - DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION..."); /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -174,8 +171,6 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->status != 0) goto cleanup; - /* Query channel properties */ - DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION..."); memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; @@ -207,8 +202,6 @@ static int storvsc_channel_init(struct hv_device *device) stor_device->target_id = vstor_packet->storage_channel_properties.target_id; - DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION..."); - memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; @@ -232,7 +225,6 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->status != 0) goto cleanup; - DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****"); cleanup: put_stor_device(device); @@ -305,13 +297,8 @@ static void storvsc_on_receive(struct hv_device *device, storvsc_on_io_completion(device, vstor_packet, request); break; case VSTOR_OPERATION_REMOVE_DEVICE: - DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION"); - /* TODO: */ - break; default: - DPRINT_INFO(STORVSC, "Unknown operation received - %d", - vstor_packet->operation); break; } } @@ -421,9 +408,6 @@ int storvsc_dev_remove(struct hv_device *device) { struct storvsc_device *stor_device; - DPRINT_INFO(STORVSC, "disabling storage device (%p)...", - device->ext); - stor_device = release_stor_device(device); /* -- cgit v1.1 From 1920da8801284c954e6edb8156a84fa9ce041128 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:07 -0700 Subject: Staging: hv: storvsc: Fix/cleanup some dated comments in storvsc.c Fix/cleanup some dated comments in storvsc.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 3730f3f..827b6a3 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -166,7 +166,6 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; } - /* TODO: Check returned version */ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) goto cleanup; @@ -193,7 +192,6 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; } - /* TODO: Check returned version */ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) goto cleanup; @@ -384,11 +382,12 @@ int storvsc_dev_add(struct hv_device *device, /* Save the channel properties to our storvsc channel */ - /* FIXME: */ /* * If we support more than 1 scsi channel, we need to set the * port number here to the scsi channel but how do we get the - * scsi channel prior to the bus scan + * scsi channel prior to the bus scan. + * + * The host does not support this. */ stor_device->port_number = device_info->port_number; @@ -545,4 +544,3 @@ int storvsc_get_major_info(struct storvsc_device_info *device_info, return -ENODEV; } - -- cgit v1.1 From f3b741658c983a2a7abc5d22a5dc60b503f6cbc3 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:08 -0700 Subject: Staging: hv: storvsc: Cleanup returned error code in storvsc_host_reset() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 29ac644..0eb8c71 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -346,7 +346,7 @@ static int storvsc_host_reset(struct hv_device *device) stor_device = get_stor_device(device); if (!stor_device) - return -1; + return -ENODEV; request = &stor_device->reset_request; vstor_packet = &request->vstor_packet; -- cgit v1.1 From 8e854680b57440a8bbfdaae05534b010060f7966 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:09 -0700 Subject: Staging: hv: storvsc: Cleanup error code returned in storvsc_probe() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 0eb8c71..69a312f 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -685,7 +685,7 @@ static int storvsc_probe(struct hv_device *device) if (ret != 0) { kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); - return -1; + return -ENODEV; } host_dev->path = device_info.path_id; @@ -706,7 +706,7 @@ static int storvsc_probe(struct hv_device *device) kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); - return -1; + return -ENODEV; } scsi_scan_host(host); -- cgit v1.1 From b06efc199f9b8cc49e47d441f837a2dbe4971e4e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:10 -0700 Subject: Staging: hv: storvsc: Cleanup returned error code in storvsc_drv_init() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 69a312f..faa8d57 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -740,7 +740,7 @@ static int __init storvsc_drv_init(void) if (max_outstanding_req_per_channel < STORVSC_MAX_IO_REQUESTS) - return -1; + return -EINVAL; return vmbus_driver_register(&storvsc_drv); } -- cgit v1.1 From 51a805d0ce0f78810fd90d4e9eafd8a0ab4bdb58 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:11 -0700 Subject: Staging: hv: netvsc: Cleanup the returned error code in netvsc_probe() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 0b8ac1a..90a3198 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -338,7 +338,7 @@ static int netvsc_probe(struct hv_device *dev) net = alloc_etherdev(sizeof(struct net_device_context)); if (!net) - return -1; + return -ENOMEM; /* Set initial state */ netif_carrier_off(net); -- cgit v1.1 From a3e00530469baa39ccc08b1731a4e120bd63012f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:12 -0700 Subject: Staging: hv: netvsc: Cleanup error return codes in netvsc_destroy_recv_buf() Cleanup error return codes in netvsc_destroy_recv_buf(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index b89ac7e..baa0c8d 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -160,7 +160,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) if (ret != 0) { dev_err(&net_device->dev->device, "unable to send " "revoke receive buffer to netvsp"); - return -1; + return ret; } } @@ -175,7 +175,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) if (ret != 0) { dev_err(&net_device->dev->device, "unable to teardown receive buffer's gpadl"); - return -1; + return -ret; } net_device->recv_buf_gpadl_handle = 0; } -- cgit v1.1 From 927bc33c0a239b706635b23c5cc1f3df2a3c8b86 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:13 -0700 Subject: Staging: hv: netvsc: Cleanup error return values in netvsc_init_recv_buf() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index baa0c8d..5703fd7 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -207,7 +207,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) if (!net_device) { dev_err(&device->device, "unable to get net device..." "device being destroyed?"); - return -1; + return -ENODEV; } net_device->recv_buf = @@ -216,7 +216,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) if (!net_device->recv_buf) { dev_err(&device->device, "unable to allocate receive " "buffer of size %d", net_device->recv_buf_size); - ret = -1; + ret = -ENOMEM; goto cleanup; } @@ -269,7 +269,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) "initialzation with NetVsp - status %d", init_packet->msg.v1_msg. send_recv_buf_complete.status); - ret = -1; + ret = -EINVAL; goto cleanup; } @@ -281,7 +281,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) net_device->recv_section = kmalloc(net_device->recv_section_cnt * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL); if (net_device->recv_section == NULL) { - ret = -1; + ret = -EINVAL; goto cleanup; } @@ -297,7 +297,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) */ if (net_device->recv_section_cnt != 1 || net_device->recv_section->offset != 0) { - ret = -1; + ret = -EINVAL; goto cleanup; } -- cgit v1.1 From 0f48c72ca63a6e1da7f226163c36fecd7a923fed Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:14 -0700 Subject: Staging: hv: netvsc: Cleanup error returns in netvsc_connect_vsp() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 5703fd7..9cc126b 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -323,7 +323,7 @@ static int netvsc_connect_vsp(struct hv_device *device) if (!net_device) { dev_err(&device->device, "unable to get net device..." "device being destroyed?"); - return -1; + return -ENODEV; } init_packet = &net_device->channel_init_pkt; @@ -354,13 +354,13 @@ static int netvsc_connect_vsp(struct hv_device *device) if (init_packet->msg.init_msg.init_complete.status != NVSP_STAT_SUCCESS) { - ret = -1; + ret = -EINVAL; goto cleanup; } if (init_packet->msg.init_msg.init_complete. negotiated_protocol_ver != NVSP_PROTOCOL_VERSION_1) { - ret = -1; + ret = -EPROTO; goto cleanup; } /* Send the ndis version */ @@ -381,10 +381,8 @@ static int netvsc_connect_vsp(struct hv_device *device) sizeof(struct nvsp_message), (unsigned long)init_packet, VM_PKT_DATA_INBAND, 0); - if (ret != 0) { - ret = -1; + if (ret != 0) goto cleanup; - } /* Post the big receive buffer to NetVSP */ ret = netvsc_init_recv_buf(device); -- cgit v1.1 From ff2bd69ae3ec164b606114fcbd9b9e4d5f2bcdc7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:15 -0700 Subject: Staging: hv: netvsc: Cleanup error return values in netvsc_send() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 9cc126b..f7f4957 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -409,7 +409,7 @@ int netvsc_device_remove(struct hv_device *device) net_device = release_outbound_net_device(device); if (!net_device) { dev_err(&device->device, "No net device present!!"); - return -1; + return -ENODEV; } /* Wait for all send completions */ @@ -499,7 +499,7 @@ int netvsc_send(struct hv_device *device, if (!net_device) { dev_err(&device->device, "net device (%p) shutting down..." "ignoring outbound packets", net_device); - return -2; + return -ENODEV; } sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; -- cgit v1.1 From ace163a85a9a98e7f91db3a23db3f63689038f1e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:16 -0700 Subject: Staging: hv: netvsc: Cleanup error return codes in netvsc_device_add() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index f7f4957..b6e1fb9 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -918,7 +918,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) net_device = alloc_net_device(device); if (!net_device) { - ret = -1; + ret = -ENOMEM; goto cleanup; } @@ -947,7 +947,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) if (ret != 0) { dev_err(&device->device, "unable to open channel: %d", ret); - ret = -1; goto cleanup; } @@ -959,7 +958,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) if (ret != 0) { dev_err(&device->device, "unable to connect to NetVSP - %d", ret); - ret = -1; goto close; } -- cgit v1.1 From 62c0743ef00cb0ad0b32b05fb96acd4d8e7391dd Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:17 -0700 Subject: Staging: hv: netvsc: Cleanup error codes in rndis_filter_receive() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index dbb5201..8e1ef00 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -358,14 +358,14 @@ int rndis_filter_receive(struct hv_device *dev, if (!net_dev->extension) { dev_err(&dev->device, "got rndis message but no rndis device - " "dropping this message!\n"); - return -1; + return -ENODEV; } rndis_dev = (struct rndis_device *)net_dev->extension; if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { dev_err(&dev->device, "got rndis message but rndis device " "uninitialized...dropping this message!\n"); - return -1; + return -ENODEV; } rndis_hdr = (struct rndis_message *)kmap_atomic( -- cgit v1.1 From de6e0580d5884942f58a636902e5b0225f38b8cf Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:18 -0700 Subject: Staging: hv: netvsc: Cleanup error code in rndis_filter_query_device() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 8e1ef00..f26886d 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -437,7 +437,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(struct rndis_query_request)); if (!request) { - ret = -1; + ret = -ENOMEM; goto Cleanup; } -- cgit v1.1 From 58ef3977ce8e0edba374dd7645e59cf5afdc6447 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:19 -0700 Subject: Staging: hv: netvsc: Cleanup error return values in rndis_filter_set_packet_filter() Use standard Linux error codes and cleanup some error paths. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index f26886d..f5f3052 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -511,7 +511,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32)); if (!request) { - ret = -1; + ret = -ENOMEM; goto Cleanup; } @@ -531,7 +531,6 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { - ret = -1; dev_err(&dev->net_dev->dev->device, "timeout before we got a set response...\n"); /* @@ -540,8 +539,6 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, */ goto Exit; } else { - if (ret > 0) - ret = 0; set_complete = &request->response_msg.msg.set_complete; status = set_complete->status; } -- cgit v1.1 From bc49b92671632d09a0fa6651c4fdf2b9ab0632ee Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:20 -0700 Subject: Staging: hv: netvsc: Cleanup error returns in rndis_filter_init_device() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index f5f3052..a71f29d 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -562,7 +562,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); if (!request) { - ret = -1; + ret = -ENOMEM; goto Cleanup; } @@ -596,7 +596,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) ret = 0; } else { dev->state = RNDIS_DEV_UNINITIALIZED; - ret = -1; + ret = -EINVAL; } Cleanup: -- cgit v1.1 From 327efbae1f96743c9b208e8a4c667eea9b8cf6c0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:21 -0700 Subject: Staging: hv: netvsc: Cleanup error code in rndis_filter_device_add() Use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index a71f29d..f0d1362 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -673,7 +673,7 @@ int rndis_filter_device_add(struct hv_device *dev, rndisDevice = get_rndis_device(); if (!rndisDevice) - return -1; + return -ENODEV; /* * Let the inner driver handle this first to create the netvsc channel -- cgit v1.1 From fdb3c32cb7b80d28f23f005543eb4f0d6e88c2a3 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:22 -0700 Subject: Staging: hv: mouse: Change the jump label Cleanup to cleanup Change the jump label "Cleanup" to "cleanup". Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index d7e24bc..07a6584 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -336,7 +336,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, if (!input_device->hid_desc) { pr_err("unable to allocate hid descriptor - size %d", desc->bLength); - goto Cleanup; + goto cleanup; } memcpy(input_device->hid_desc, desc, desc->bLength); @@ -349,7 +349,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, if (!input_device->report_desc) { pr_err("unable to allocate report descriptor - size %d", input_device->report_desc_size); - goto Cleanup; + goto cleanup; } memcpy(input_device->report_desc, @@ -376,7 +376,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, if (ret != 0) { pr_err("unable to send synthhid device info ack - ret %d", ret); - goto Cleanup; + goto cleanup; } input_device->device_wait_condition = 1; @@ -384,7 +384,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, return; -Cleanup: +cleanup: kfree(input_device->hid_desc); input_device->hid_desc = NULL; @@ -603,7 +603,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) { pr_err("unable to send synthhid protocol request."); - goto Cleanup; + goto cleanup; } input_dev->protocol_wait_condition = 0; @@ -611,7 +611,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) input_dev->protocol_wait_condition, msecs_to_jiffies(1000)); if (input_dev->protocol_wait_condition == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } response = &input_dev->protocol_resp; @@ -620,7 +620,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) pr_err("synthhid protocol request failed (version %d)", SYNTHHID_INPUT_VERSION); ret = -1; - goto Cleanup; + goto cleanup; } input_dev->device_wait_condition = 0; @@ -628,7 +628,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) input_dev->device_wait_condition, msecs_to_jiffies(1000)); if (input_dev->device_wait_condition == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } /* @@ -640,7 +640,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) else ret = -1; -Cleanup: +cleanup: put_input_device(device); return ret; @@ -658,7 +658,7 @@ static int mousevsc_on_device_add(struct hv_device *device, if (!input_dev) { ret = -1; - goto Cleanup; + goto cleanup; } input_dev->init_complete = false; @@ -711,7 +711,7 @@ static int mousevsc_on_device_add(struct hv_device *device, input_dev->init_complete = true; -Cleanup: +cleanup: return ret; } -- cgit v1.1 From 1c627870f005149e815a7db00084160cfde1bef8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:24 -0700 Subject: Staging: hv: netvsc: Change the jump label Cleanup to cleanup Change the jump label "Cleanup" to "cleanup". Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index f0d1362..79dfe78 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -438,7 +438,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, RNDIS_MESSAGE_SIZE(struct rndis_query_request)); if (!request) { ret = -ENOMEM; - goto Cleanup; + goto cleanup; } /* Setup the rndis query */ @@ -450,12 +450,12 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, ret = rndis_filter_send_request(dev, request); if (ret != 0) - goto Cleanup; + goto cleanup; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } /* Copy the response back */ @@ -463,7 +463,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, if (query_complete->info_buflen > inresult_size) { ret = -1; - goto Cleanup; + goto cleanup; } memcpy(result, @@ -473,7 +473,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, *result_size = query_complete->info_buflen; -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); @@ -512,7 +512,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, sizeof(u32)); if (!request) { ret = -ENOMEM; - goto Cleanup; + goto cleanup; } /* Setup the rndis set */ @@ -526,7 +526,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, ret = rndis_filter_send_request(dev, request); if (ret != 0) - goto Cleanup; + goto cleanup; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); @@ -543,7 +543,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, status = set_complete->status; } -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); Exit: @@ -563,7 +563,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); if (!request) { ret = -ENOMEM; - goto Cleanup; + goto cleanup; } /* Setup the rndis set */ @@ -578,7 +578,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) ret = rndis_filter_send_request(dev, request); if (ret != 0) { dev->state = RNDIS_DEV_UNINITIALIZED; - goto Cleanup; + goto cleanup; } @@ -586,7 +586,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } init_complete = &request->response_msg.msg.init_complete; @@ -599,7 +599,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) ret = -EINVAL; } -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); @@ -615,7 +615,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev) request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(struct rndis_halt_request)); if (!request) - goto Cleanup; + goto cleanup; /* Setup the rndis set */ halt = &request->request_msg.msg.halt_req; @@ -626,7 +626,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev) dev->state = RNDIS_DEV_UNINITIALIZED; -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); return; -- cgit v1.1 From 5585d81e0a52f7994b8cdc6a8927b425c068444a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:25 -0700 Subject: Staging: hv: netvsc: Change the jump label Exit to exit Change the jump lable "Exit" to "exit". Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 79dfe78..6db48b9 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -537,7 +537,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, * We can't deallocate the request since we may still receive a * send completion for it. */ - goto Exit; + goto exit; } else { set_complete = &request->response_msg.msg.set_complete; status = set_complete->status; @@ -546,7 +546,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, cleanup: if (request) put_rndis_request(dev, request); -Exit: +exit: return ret; } -- cgit v1.1 From 18d08aff878c827e8a7a0ea10da597a44ddfe7bc Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:49:23 -0700 Subject: Staging: hv: mouse: Get rid of the unused PCI signature Get rid of the unused PCI signature in the mouse driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 07a6584..dfa8ae8 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include "hyperv.h" @@ -935,26 +933,6 @@ static void __exit mousevsc_exit(void) vmbus_driver_unregister(&mousevsc_drv); } -/* - * We don't want to automatically load this driver just yet, it's quite - * broken. It's safe if you want to load it yourself manually, but - * don't inflict it on unsuspecting users, that's just mean. - */ -#if 0 - -/* - * We use a PCI table to determine if we should autoload this driver This is - * needed by distro tools to determine if the hyperv drivers should be - * installed and/or configured. We don't do anything else with the table, but - * it needs to be present. - */ -static const struct pci_device_id microsoft_hv_pci_table[] = { - { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); -#endif - MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); module_init(mousevsc_init); -- cgit v1.1 From 4bc694057bc95049ed8d451c2e142c79bbf97328 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 16:36:52 -0700 Subject: Staging: hv: hv_mouse: remove deviceinfo_callback function It's not needed, so just inline the two lines. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index dfa8ae8..8c4ae37 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -173,8 +173,13 @@ struct mousevsc_dev { struct hv_input_dev_info hid_dev_info; }; +struct input_device_context { + struct hv_device *device_ctx; + struct hid_device *hid_device; + struct hv_input_dev_info device_info; + int connected; +}; -static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info); static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); @@ -651,6 +656,7 @@ static int mousevsc_on_device_add(struct hv_device *device, struct mousevsc_dev *input_dev; struct hv_driver *input_drv; struct hv_input_dev_info dev_info; + struct input_device_context *input_device_ctx; input_dev = alloc_input_device(device); @@ -697,7 +703,9 @@ static int mousevsc_on_device_add(struct hv_device *device, strcpy(dev_info.name, "Microsoft Vmbus HID-compliant Mouse"); /* Send the device info back up */ - deviceinfo_callback(device, &dev_info); + input_device_ctx = dev_get_drvdata(&device->device); + memcpy(&input_device_ctx->device_info, &dev_info, + sizeof(struct hv_input_dev_info)); /* Send the report desc back up */ /* workaround SA-167 */ @@ -752,28 +760,6 @@ static int mousevsc_on_device_remove(struct hv_device *device) } -/* - * Data types - */ -struct input_device_context { - struct hv_device *device_ctx; - struct hid_device *hid_device; - struct hv_input_dev_info device_info; - int connected; -}; - - -static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info) -{ - struct input_device_context *input_device_ctx = - dev_get_drvdata(&dev->device); - - memcpy(&input_device_ctx->device_info, info, - sizeof(struct hv_input_dev_info)); - - DPRINT_INFO(INPUTVSC_DRV, "%s", __func__); -} - static void inputreport_callback(struct hv_device *dev, void *packet, u32 len) { int ret = 0; -- cgit v1.1 From 3f4636e625204e74986e9f1f845229ebd6235f9e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 16:41:06 -0700 Subject: Staging: hv: hv_mouse: remove inputreport_callback function It's not needed, so just inline the two lines. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 8c4ae37..257684e 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -180,7 +180,6 @@ struct input_device_context { int connected; }; -static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); static struct mousevsc_dev *alloc_input_device(struct hv_device *device) @@ -403,6 +402,7 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, struct synthhid_input_report *input_report) { struct hv_driver *input_drv; + struct input_device_context *input_dev_ctx; if (!input_device->init_complete) { pr_info("Initialization incomplete...ignoring input_report msg"); @@ -411,9 +411,11 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, input_drv = drv_to_hv_drv(input_device->device->device.driver); - inputreport_callback(input_device->device, - input_report->buffer, - input_report->header.size); + input_dev_ctx = dev_get_drvdata(&input_device->device->device); + + hid_input_report(input_dev_ctx->hid_device, + HID_INPUT_REPORT, input_report->buffer, input_report->header.size, 1); + } static void mousevsc_on_receive(struct hv_device *device, @@ -760,19 +762,6 @@ static int mousevsc_on_device_remove(struct hv_device *device) } -static void inputreport_callback(struct hv_device *dev, void *packet, u32 len) -{ - int ret = 0; - - struct input_device_context *input_dev_ctx = - dev_get_drvdata(&dev->device); - - ret = hid_input_report(input_dev_ctx->hid_device, - HID_INPUT_REPORT, packet, len, 1); - - DPRINT_DBG(INPUTVSC_DRV, "hid_input_report (ret %d)", ret); -} - static int mousevsc_hid_open(struct hid_device *hid) { return 0; -- cgit v1.1 From 4ab0871ddd1bfdc514f93472cfd68290ecdb62c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 16:47:43 -0700 Subject: Staging: hv: hv_mouse: remove a forward declaration This moves some functions around to remove a forward declaration. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 126 +++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 64 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 257684e..083f28f 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -180,8 +180,6 @@ struct input_device_context { int connected; }; -static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); - static struct mousevsc_dev *alloc_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; @@ -651,6 +649,68 @@ cleanup: return ret; } +static int mousevsc_hid_open(struct hid_device *hid) +{ + return 0; +} + +static void mousevsc_hid_close(struct hid_device *hid) +{ +} + +static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) +{ + struct input_device_context *input_device_ctx = + dev_get_drvdata(&dev->device); + struct hid_device *hid_dev; + + /* hid_debug = -1; */ + hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); + + if (hid_parse_report(hid_dev, packet, len)) { + DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); + return; + } + + if (hid_dev) { + DPRINT_INFO(INPUTVSC_DRV, "hid_device created"); + + hid_dev->ll_driver->open = mousevsc_hid_open; + hid_dev->ll_driver->close = mousevsc_hid_close; + + hid_dev->bus = BUS_VIRTUAL; + hid_dev->vendor = input_device_ctx->device_info.vendor; + hid_dev->product = input_device_ctx->device_info.product; + hid_dev->version = input_device_ctx->device_info.version; + hid_dev->dev = dev->device; + + sprintf(hid_dev->name, "%s", + input_device_ctx->device_info.name); + + /* + * HJ Do we want to call it with a 0 + */ + if (!hidinput_connect(hid_dev, 0)) { + hid_dev->claimed |= HID_CLAIMED_INPUT; + + input_device_ctx->connected = 1; + + DPRINT_INFO(INPUTVSC_DRV, + "HID device claimed by input\n"); + } + + if (!hid_dev->claimed) { + DPRINT_ERR(INPUTVSC_DRV, + "HID device not claimed by " + "input or hiddev\n"); + } + + input_device_ctx->hid_device = hid_dev; + } + + kfree(hid_dev); +} + static int mousevsc_on_device_add(struct hv_device *device, void *additional_info) { @@ -762,15 +822,6 @@ static int mousevsc_on_device_remove(struct hv_device *device) } -static int mousevsc_hid_open(struct hid_device *hid) -{ - return 0; -} - -static void mousevsc_hid_close(struct hid_device *hid) -{ -} - static int mousevsc_probe(struct hv_device *dev) { int ret = 0; @@ -826,59 +877,6 @@ static int mousevsc_remove(struct hv_device *dev) return ret; } -static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) -{ - struct input_device_context *input_device_ctx = - dev_get_drvdata(&dev->device); - struct hid_device *hid_dev; - - /* hid_debug = -1; */ - hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); - - if (hid_parse_report(hid_dev, packet, len)) { - DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); - return; - } - - if (hid_dev) { - DPRINT_INFO(INPUTVSC_DRV, "hid_device created"); - - hid_dev->ll_driver->open = mousevsc_hid_open; - hid_dev->ll_driver->close = mousevsc_hid_close; - - hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_device_ctx->device_info.vendor; - hid_dev->product = input_device_ctx->device_info.product; - hid_dev->version = input_device_ctx->device_info.version; - hid_dev->dev = dev->device; - - sprintf(hid_dev->name, "%s", - input_device_ctx->device_info.name); - - /* - * HJ Do we want to call it with a 0 - */ - if (!hidinput_connect(hid_dev, 0)) { - hid_dev->claimed |= HID_CLAIMED_INPUT; - - input_device_ctx->connected = 1; - - DPRINT_INFO(INPUTVSC_DRV, - "HID device claimed by input\n"); - } - - if (!hid_dev->claimed) { - DPRINT_ERR(INPUTVSC_DRV, - "HID device not claimed by " - "input or hiddev\n"); - } - - input_device_ctx->hid_device = hid_dev; - } - - kfree(hid_dev); -} - static const struct hv_vmbus_device_id id_table[] = { /* Mouse guid */ { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, -- cgit v1.1 From 6a180978aea7cb231c60b69b078ec339f40e2faa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 16:51:28 -0700 Subject: Staging: hv: hv_mouse: fix up remove() function This function obviously never worked, it was a cut-and-paste from the probe() function. Rewrite it to do what it is supposed to do at least in theory. As to if it works yet, well, it's not worse than it was before, so this can't hurt. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 083f28f..090736a 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -847,15 +847,10 @@ static int mousevsc_probe(struct hv_device *dev) static int mousevsc_remove(struct hv_device *dev) { - int ret = 0; - struct input_device_context *input_dev_ctx; + int ret; - input_dev_ctx = kmalloc(sizeof(struct input_device_context), - GFP_KERNEL); - - dev_set_drvdata(&dev->device, input_dev_ctx); - + input_dev_ctx = dev_get_drvdata(&dev->device); if (input_dev_ctx->connected) { hidinput_disconnect(input_dev_ctx->hid_device); input_dev_ctx->connected = 0; @@ -866,7 +861,6 @@ static int mousevsc_remove(struct hv_device *dev) * is being removed */ ret = mousevsc_on_device_remove(dev); - if (ret != 0) { DPRINT_ERR(INPUTVSC_DRV, "unable to remove vsc device (ret %d)", ret); -- cgit v1.1 From 0fb07a87ec663652bea02a54faa05fb4b3d0c20f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:00 -0700 Subject: Staging: hv: storvsc: Inline free_stor_device() Inline the code for free_stor_device() and get rid of the function. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 827b6a3..8c62829 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -51,10 +51,6 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) return stor_device; } -static inline void free_stor_device(struct storvsc_device *device) -{ - kfree(device); -} /* Get the stordevice object iff exists and its refcount > 0 */ static inline struct storvsc_device *must_get_stor_device( @@ -394,7 +390,7 @@ int storvsc_dev_add(struct hv_device *device, /* Send it back up */ ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size); if (ret) { - free_stor_device(stor_device); + kfree(stor_device); return ret; } device_info->path_id = stor_device->path_id; @@ -422,7 +418,7 @@ int storvsc_dev_remove(struct hv_device *device) /* Close the channel */ vmbus_close(device->channel); - free_stor_device(stor_device); + kfree(stor_device); return 0; } -- cgit v1.1 From bdbc49706be445d0f5c16c0add979d52d01a7b2c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:01 -0700 Subject: Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device On entry into storvsc_on_io_completion() we have already acquired a reference on the stor_device; there is no need to acquire an additional reference here. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 8c62829..cd38cd6 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -232,9 +232,7 @@ static void storvsc_on_io_completion(struct hv_device *device, struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; - stor_device = must_get_stor_device(device); - if (!stor_device) - return; + stor_device = (struct storvsc_device *)device->ext; stor_pkt = &request->vstor_packet; @@ -279,7 +277,6 @@ static void storvsc_on_io_completion(struct hv_device *device, wake_up(&stor_device->waiting_to_drain); - put_stor_device(device); } static void storvsc_on_receive(struct hv_device *device, -- cgit v1.1 From bf49e809986f11c9046239e3d2439b5581f2421b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:02 -0700 Subject: Staging: hv: storvsc: Rename must_get_stor_device() In preparation for cleaning up how we manage reference counts on the stor device, clearly distinguish why we are attempting to acquire a reference. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index cd38cd6..89708b1 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) return NULL; /* Set to 2 to allow both inbound and outbound traffics */ - /* (ie get_stor_device() and must_get_stor_device()) to proceed. */ + /* (ie get_stor_device() and get_in_stor_device()) to proceed. */ atomic_cmpxchg(&stor_device->ref_count, 0, 2); init_waitqueue_head(&stor_device->waiting_to_drain); @@ -53,7 +53,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) /* Get the stordevice object iff exists and its refcount > 0 */ -static inline struct storvsc_device *must_get_stor_device( +static inline struct storvsc_device *get_in_stor_device( struct hv_device *device) { struct storvsc_device *stor_device; @@ -305,7 +305,7 @@ static void storvsc_on_channel_callback(void *context) int ret; - stor_device = must_get_stor_device(device); + stor_device = get_in_stor_device(device); if (!stor_device) return; -- cgit v1.1 From 1eaaddf93853b222a08ec37d4d8c4edc1085d312 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:03 -0700 Subject: Staging: hv: storvsc: Rename get_stor_device() In preparation for cleaning up how we manage reference counts on the stor device, clearly distinguish why we are attempting to acquire a reference. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_storage.h | 3 ++- drivers/staging/hv/storvsc.c | 8 ++++---- drivers/staging/hv/storvsc_drv.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h index a01f9a0..a224413 100644 --- a/drivers/staging/hv/hyperv_storage.h +++ b/drivers/staging/hv/hyperv_storage.h @@ -288,7 +288,8 @@ struct storvsc_device { /* Get the stordevice object iff exists and its refcount > 1 */ -static inline struct storvsc_device *get_stor_device(struct hv_device *device) +static inline struct storvsc_device *get_out_stor_device( + struct hv_device *device) { struct storvsc_device *stor_device; diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 89708b1..313a3f8 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) return NULL; /* Set to 2 to allow both inbound and outbound traffics */ - /* (ie get_stor_device() and get_in_stor_device()) to proceed. */ + /* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */ atomic_cmpxchg(&stor_device->ref_count, 0, 2); init_waitqueue_head(&stor_device->waiting_to_drain); @@ -67,7 +67,7 @@ static inline struct storvsc_device *get_in_stor_device( return stor_device; } -/* Drop ref count to 1 to effectively disable get_stor_device() */ +/* Drop ref count to 1 to effectively disable get_out_stor_device() */ static inline struct storvsc_device *release_stor_device( struct hv_device *device) { @@ -105,7 +105,7 @@ static int storvsc_channel_init(struct hv_device *device) struct vstor_packet *vstor_packet; int ret, t; - stor_device = get_stor_device(device); + stor_device = get_out_stor_device(device); if (!stor_device) return -ENODEV; @@ -427,7 +427,7 @@ int storvsc_do_io(struct hv_device *device, int ret = 0; vstor_packet = &request->vstor_packet; - stor_device = get_stor_device(device); + stor_device = get_out_stor_device(device); if (!stor_device) return -ENODEV; diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index faa8d57..5b2004f 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -344,7 +344,7 @@ static int storvsc_host_reset(struct hv_device *device) int ret, t; - stor_device = get_stor_device(device); + stor_device = get_out_stor_device(device); if (!stor_device) return -ENODEV; -- cgit v1.1 From df977d6c90632b3868055862262529007019d4ef Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:04 -0700 Subject: Staging: hv: storvsc: Cleanup alloc_stor_device() Cleanup alloc_stor_device(), we can set the ref_count directly. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 313a3f8..48bd8da 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -42,7 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) /* Set to 2 to allow both inbound and outbound traffics */ /* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */ - atomic_cmpxchg(&stor_device->ref_count, 0, 2); + atomic_set(&stor_device->ref_count, 2); init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; -- cgit v1.1 From f6c17484eb386014ee52d9edc8b3e8263d57c640 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:05 -0700 Subject: Staging: hv: storvsc: Introduce state to manage the lifecycle of stor device Introduce state to manage the lifecycle of stor device. This would be the basis for managing the references on the stor object. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_storage.h | 2 +- drivers/staging/hv/storvsc.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h index a224413..d93bf93 100644 --- a/drivers/staging/hv/hyperv_storage.h +++ b/drivers/staging/hv/hyperv_storage.h @@ -266,7 +266,7 @@ struct storvsc_device { /* 0 indicates the device is being destroyed */ atomic_t ref_count; - + bool destroy; bool drain_notify; atomic_t num_outstanding_req; diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 48bd8da..0f8c609 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -43,7 +43,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) /* Set to 2 to allow both inbound and outbound traffics */ /* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */ atomic_set(&stor_device->ref_count, 2); - + stor_device->destroy = false; init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; device->ext = stor_device; @@ -399,9 +399,15 @@ int storvsc_dev_add(struct hv_device *device, int storvsc_dev_remove(struct hv_device *device) { struct storvsc_device *stor_device; + unsigned long flags; + stor_device = release_stor_device(device); + spin_lock_irqsave(&device->channel->inbound_lock, flags); + stor_device->destroy = true; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + /* * At this point, all outbound traffic should be disable. We * only allow inbound traffic (responses) to proceed so that -- cgit v1.1 From 582f445fde4886959deacf93b6dea6817f41ba88 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:06 -0700 Subject: Staging: hv: storvsc: Prevent outgoing traffic when stor dev is being destroyed Prevent outgoing traffic when stor dev is destroyed. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_storage.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h index d93bf93..1a59ca0 100644 --- a/drivers/staging/hv/hyperv_storage.h +++ b/drivers/staging/hv/hyperv_storage.h @@ -294,7 +294,8 @@ static inline struct storvsc_device *get_out_stor_device( struct storvsc_device *stor_device; stor_device = (struct storvsc_device *)device->ext; - if (stor_device && atomic_read(&stor_device->ref_count) > 1) + if (stor_device && (atomic_read(&stor_device->ref_count) > 1) && + !stor_device->destroy) atomic_inc(&stor_device->ref_count); else stor_device = NULL; -- cgit v1.1 From c352ee8f610bb136d5666b142bff8f48fa7a9289 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:07 -0700 Subject: Staging: hv: storvsc: Get rid of release_stor_device() by inlining the code Get rid of release_stor_device() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 0f8c609..1976a34 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -67,21 +67,6 @@ static inline struct storvsc_device *get_in_stor_device( return stor_device; } -/* Drop ref count to 1 to effectively disable get_out_stor_device() */ -static inline struct storvsc_device *release_stor_device( - struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = (struct storvsc_device *)device->ext; - - /* Busy wait until the ref drop to 2, then set it to 1 */ - while (atomic_cmpxchg(&stor_device->ref_count, 2, 1) != 2) - udelay(100); - - return stor_device; -} - /* Drop ref count to 0. No one can use stor_device object. */ static inline struct storvsc_device *final_release_stor_device( struct hv_device *device) @@ -401,8 +386,8 @@ int storvsc_dev_remove(struct hv_device *device) struct storvsc_device *stor_device; unsigned long flags; - - stor_device = release_stor_device(device); + stor_device = (struct storvsc_device *)device->ext; + atomic_dec(&stor_device->ref_count); spin_lock_irqsave(&device->channel->inbound_lock, flags); stor_device->destroy = true; -- cgit v1.1 From a5b2359b05925ade4b9a645b9e45a6c4b8fb1ff0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:08 -0700 Subject: Staging: hv: storvsc: Get rid of final_release_stor_device() by inlining code Get rid of final_release_stor_device() by inlining code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 1976a34..3e9829f 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -67,22 +67,6 @@ static inline struct storvsc_device *get_in_stor_device( return stor_device; } -/* Drop ref count to 0. No one can use stor_device object. */ -static inline struct storvsc_device *final_release_stor_device( - struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = (struct storvsc_device *)device->ext; - - /* Busy wait until the ref drop to 1, then set it to 0 */ - while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1) - udelay(100); - - device->ext = NULL; - return stor_device; -} - static int storvsc_channel_init(struct hv_device *device) { struct storvsc_device *stor_device; @@ -401,7 +385,12 @@ int storvsc_dev_remove(struct hv_device *device) storvsc_wait_to_drain(stor_device); - stor_device = final_release_stor_device(device); + /* + * Since we have already drained, we don't need to busy wait + * as was done in final_release_stor_device() + */ + atomic_set(&stor_device->ref_count, 0); + device->ext = NULL; /* Close the channel */ vmbus_close(device->channel); -- cgit v1.1 From 5e6f4d069f102b6a49433943cf37e3bdc52e2314 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:09 -0700 Subject: Staging: hv: storvsc: Get rid of the reference counting in struct storvsc_device Get rid of the reference counting in struct storvsc_device. We manage the lifecycle with the following logic: If the device is marked for destruction, we dot allow any outgoing traffic on the device. Incoming traffic is allowed only to drain pending outgoing traffic. Note that while the upper level code in Linux deals with outstanding I/Os, we may have situations on Hyper-V where some book keeping messages are sent out that the upper level Linux code may not be aware of. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_storage.h | 18 ++---------------- drivers/staging/hv/storvsc.c | 33 +++++++++++++++++++++------------ drivers/staging/hv/storvsc_drv.c | 1 - 3 files changed, 23 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h index 1a59ca0..687cdc5 100644 --- a/drivers/staging/hv/hyperv_storage.h +++ b/drivers/staging/hv/hyperv_storage.h @@ -264,8 +264,6 @@ struct storvsc_major_info { struct storvsc_device { struct hv_device *device; - /* 0 indicates the device is being destroyed */ - atomic_t ref_count; bool destroy; bool drain_notify; atomic_t num_outstanding_req; @@ -287,32 +285,20 @@ struct storvsc_device { }; -/* Get the stordevice object iff exists and its refcount > 1 */ static inline struct storvsc_device *get_out_stor_device( struct hv_device *device) { struct storvsc_device *stor_device; stor_device = (struct storvsc_device *)device->ext; - if (stor_device && (atomic_read(&stor_device->ref_count) > 1) && - !stor_device->destroy) - atomic_inc(&stor_device->ref_count); - else + + if (stor_device && stor_device->destroy) stor_device = NULL; return stor_device; } -static inline void put_stor_device(struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = (struct storvsc_device *)device->ext; - - atomic_dec(&stor_device->ref_count); -} - static inline void storvsc_wait_to_drain(struct storvsc_device *dev) { dev->drain_notify = true; diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c index 3e9829f..fb7b3ca 100644 --- a/drivers/staging/hv/storvsc.c +++ b/drivers/staging/hv/storvsc.c @@ -40,9 +40,6 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) if (!stor_device) return NULL; - /* Set to 2 to allow both inbound and outbound traffics */ - /* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */ - atomic_set(&stor_device->ref_count, 2); stor_device->destroy = false; init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; @@ -52,19 +49,31 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) } -/* Get the stordevice object iff exists and its refcount > 0 */ static inline struct storvsc_device *get_in_stor_device( struct hv_device *device) { struct storvsc_device *stor_device; + unsigned long flags; + spin_lock_irqsave(&device->channel->inbound_lock, flags); stor_device = (struct storvsc_device *)device->ext; - if (stor_device && atomic_read(&stor_device->ref_count)) - atomic_inc(&stor_device->ref_count); - else + + if (!stor_device) + goto get_in_err; + + /* + * If the device is being destroyed; allow incoming + * traffic only to cleanup outstanding requests. + */ + + if (stor_device->destroy && + (atomic_read(&stor_device->num_outstanding_req) == 0)) stor_device = NULL; +get_in_err: + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); return stor_device; + } static int storvsc_channel_init(struct hv_device *device) @@ -190,7 +199,6 @@ static int storvsc_channel_init(struct hv_device *device) cleanup: - put_stor_device(device); return ret; } @@ -303,7 +311,6 @@ static void storvsc_on_channel_callback(void *context) } } while (1); - put_stor_device(device); return; } @@ -371,7 +378,6 @@ int storvsc_dev_remove(struct hv_device *device) unsigned long flags; stor_device = (struct storvsc_device *)device->ext; - atomic_dec(&stor_device->ref_count); spin_lock_irqsave(&device->channel->inbound_lock, flags); stor_device->destroy = true; @@ -388,9 +394,13 @@ int storvsc_dev_remove(struct hv_device *device) /* * Since we have already drained, we don't need to busy wait * as was done in final_release_stor_device() + * Note that we cannot set the ext pointer to NULL until + * we have drained - to drain the outgoing packets, we need to + * allow incoming packets. */ - atomic_set(&stor_device->ref_count, 0); + spin_lock_irqsave(&device->channel->inbound_lock, flags); device->ext = NULL; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* Close the channel */ vmbus_close(device->channel); @@ -448,7 +458,6 @@ int storvsc_do_io(struct hv_device *device, atomic_inc(&stor_device->num_outstanding_req); - put_stor_device(device); return ret; } diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 5b2004f..ae74f50 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -378,7 +378,6 @@ static int storvsc_host_reset(struct hv_device *device) */ cleanup: - put_stor_device(device); return ret; } -- cgit v1.1 From 356c4657193c8a5b3aff84fe8cdf5ddc64742801 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:10 -0700 Subject: Staging: hv: netvsc: Inline the code for free_net_device() Inline the code for free_net_device(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index b6e1fb9..75c6ed7 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -49,14 +49,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) return net_device; } -static void free_net_device(struct netvsc_device *device) -{ - WARN_ON(atomic_read(&device->refcnt) != 0); - device->dev->ext = NULL; - kfree(device); -} - - /* Get the net device object iff exists and its refcount > 1 */ static struct netvsc_device *get_outbound_net_device(struct hv_device *device) { @@ -438,7 +430,7 @@ int netvsc_device_remove(struct hv_device *device) kfree(netvsc_packet); } - free_net_device(net_device); + kfree(net_device); return 0; } @@ -980,7 +972,7 @@ cleanup: release_outbound_net_device(device); release_inbound_net_device(device); - free_net_device(net_device); + kfree(net_device); } return ret; -- cgit v1.1 From 509ee3878b8f0f8908892579d679c123084f5ac5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:11 -0700 Subject: Staging: hv: netvsc: Cleanup alloc_net_device() Cleanup alloc_net_device(); we can directly set the refcnt. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 75c6ed7..7722102 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -41,7 +41,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) return NULL; /* Set to 2 to allow both inbound and outbound traffic */ - atomic_cmpxchg(&net_device->refcnt, 0, 2); + atomic_set(&net_device->refcnt, 2); net_device->dev = device; device->ext = net_device; -- cgit v1.1 From c38b9c7118b95aa48bfa38d3bcd241dba3d23c10 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:12 -0700 Subject: Staging: hv: netvsc: Introduce state to manage the lifecycle of net device Introduce state to manage the lifecycle of net device. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_net.h | 1 + drivers/staging/hv/netvsc.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index 5782fea..0b347c1 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -371,6 +371,7 @@ struct netvsc_device { atomic_t refcnt; atomic_t num_outstanding_sends; + bool destroy; /* * List of free preallocated hv_netvsc_packet to represent receive * packet diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 7722102..8eb4039 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -43,6 +43,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) /* Set to 2 to allow both inbound and outbound traffic */ atomic_set(&net_device->refcnt, 2); + net_device->destroy = false; net_device->dev = device; device->ext = net_device; @@ -396,6 +397,7 @@ int netvsc_device_remove(struct hv_device *device) { struct netvsc_device *net_device; struct hv_netvsc_packet *netvsc_packet, *pos; + unsigned long flags; /* Stop outbound traffic ie sends and receives completions */ net_device = release_outbound_net_device(device); @@ -404,6 +406,10 @@ int netvsc_device_remove(struct hv_device *device) return -ENODEV; } + spin_lock_irqsave(&device->channel->inbound_lock, flags); + net_device->destroy = true; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + /* Wait for all send completions */ while (atomic_read(&net_device->num_outstanding_sends)) { dev_err(&device->device, -- cgit v1.1 From 2ef7714397cd49dc378e20afa6dd19306e5f2b5e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:13 -0700 Subject: Staging: hv: netvsc: Prevent outgoing traffic when netvsc dev is destroyed Prevent outgoing traffic when netvsc dev is destroyed. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 8eb4039..67065c1 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -56,7 +56,8 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device) struct netvsc_device *net_device; net_device = device->ext; - if (net_device && atomic_read(&net_device->refcnt) > 1) + if (net_device && (atomic_read(&net_device->refcnt) > 1) && + !net_device->destroy) atomic_inc(&net_device->refcnt); else net_device = NULL; -- cgit v1.1 From 3852409b88e8ec2a8abb28db5be25a7503297208 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:14 -0700 Subject: Staging: hv: netvsc: Get rid of release_outbound_net_device() by inlining the code Get rid of release_outbound_net_device() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 67065c1..e46161d 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -88,22 +88,6 @@ static void put_net_device(struct hv_device *device) atomic_dec(&net_device->refcnt); } -static struct netvsc_device *release_outbound_net_device( - struct hv_device *device) -{ - struct netvsc_device *net_device; - - net_device = device->ext; - if (net_device == NULL) - return NULL; - - /* Busy wait until the ref drop to 2, then set it to 1 */ - while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2) - udelay(100); - - return net_device; -} - static struct netvsc_device *release_inbound_net_device( struct hv_device *device) { @@ -400,13 +384,8 @@ int netvsc_device_remove(struct hv_device *device) struct hv_netvsc_packet *netvsc_packet, *pos; unsigned long flags; - /* Stop outbound traffic ie sends and receives completions */ - net_device = release_outbound_net_device(device); - if (!net_device) { - dev_err(&device->device, "No net device present!!"); - return -ENODEV; - } - + net_device = (struct netvsc_device *)device->ext; + atomic_dec(&net_device->refcnt); spin_lock_irqsave(&device->channel->inbound_lock, flags); net_device->destroy = true; spin_unlock_irqrestore(&device->channel->inbound_lock, flags); @@ -424,6 +403,18 @@ int netvsc_device_remove(struct hv_device *device) /* Stop inbound traffic ie receives and sends completions */ net_device = release_inbound_net_device(device); + /* + * Wait until the ref cnt falls to 0. + * We have already stopped any new references + * for outgoing traffic. Also, at this point we don't have any + * incoming traffic as well. So this must be outgoing refrences + * established prior to marking the device as being destroyed. + * Since the send path is non-blocking, it is reasonable to busy + * wait here. + */ + while (atomic_read(&net_device->refcnt)) + udelay(100); + /* At this point, no one should be accessing netDevice except in here */ dev_notice(&device->device, "net device safe to remove"); @@ -976,7 +967,6 @@ cleanup: kfree(packet); } - release_outbound_net_device(device); release_inbound_net_device(device); kfree(net_device); -- cgit v1.1 From 124f506dc1bbfc79c32dd17566f09ef51f7cf863 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:15 -0700 Subject: Staging: hv: netvsc: Get rid of release_inbound_net_device() by inlining the code Get rid of release_inbound_net_device() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index e46161d..388f083 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -88,23 +88,6 @@ static void put_net_device(struct hv_device *device) atomic_dec(&net_device->refcnt); } -static struct netvsc_device *release_inbound_net_device( - struct hv_device *device) -{ - struct netvsc_device *net_device; - - net_device = device->ext; - if (net_device == NULL) - return NULL; - - /* Busy wait until the ref drop to 1, then set it to 0 */ - while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1) - udelay(100); - - device->ext = NULL; - return net_device; -} - static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) { struct nvsp_message *revoke_packet; @@ -400,9 +383,8 @@ int netvsc_device_remove(struct hv_device *device) netvsc_disconnect_vsp(net_device); - /* Stop inbound traffic ie receives and sends completions */ - net_device = release_inbound_net_device(device); - + atomic_dec(&net_device->refcnt); + device->ext = NULL; /* * Wait until the ref cnt falls to 0. * We have already stopped any new references @@ -967,8 +949,6 @@ cleanup: kfree(packet); } - release_inbound_net_device(device); - kfree(net_device); } -- cgit v1.1 From 9d88f33a1530f4241227226e7479d36ac959e9ce Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:16 -0700 Subject: Staging: hv: netvsc: Get rid of the refcnt field in struct netvsc_device Get rid of the refcnt field in struct netvsc_device. We implement the following logic to manage the life cycle of the device: If the device is being destroyed, we do not allow any outgoing traffic. Furthermore, if the device is being destroyed, we allow incoming traffic only to drain outgoing traffic. Note that the driver may send some book keeping messages to the host not known to upper level Linux code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_net.h | 1 - drivers/staging/hv/netvsc.c | 62 +++++++++++++---------------------------- 2 files changed, 20 insertions(+), 43 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index 0b347c1..af8a37f 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -369,7 +369,6 @@ struct nvsp_message { struct netvsc_device { struct hv_device *dev; - atomic_t refcnt; atomic_t num_outstanding_sends; bool destroy; /* diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 388f083..9828f0b 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -40,8 +40,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) if (!net_device) return NULL; - /* Set to 2 to allow both inbound and outbound traffic */ - atomic_set(&net_device->refcnt, 2); net_device->destroy = false; net_device->dev = device; @@ -50,43 +48,37 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) return net_device; } -/* Get the net device object iff exists and its refcount > 1 */ static struct netvsc_device *get_outbound_net_device(struct hv_device *device) { struct netvsc_device *net_device; net_device = device->ext; - if (net_device && (atomic_read(&net_device->refcnt) > 1) && - !net_device->destroy) - atomic_inc(&net_device->refcnt); - else + if (net_device && net_device->destroy) net_device = NULL; return net_device; } -/* Get the net device object iff exists and its refcount > 0 */ static struct netvsc_device *get_inbound_net_device(struct hv_device *device) { struct netvsc_device *net_device; + unsigned long flags; + spin_lock_irqsave(&device->channel->inbound_lock, flags); net_device = device->ext; - if (net_device && atomic_read(&net_device->refcnt)) - atomic_inc(&net_device->refcnt); - else + + if (!net_device) + goto get_in_err; + + if (net_device->destroy && + atomic_read(&net_device->num_outstanding_sends) == 0) net_device = NULL; +get_in_err: + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); return net_device; } -static void put_net_device(struct hv_device *device) -{ - struct netvsc_device *net_device; - - net_device = device->ext; - - atomic_dec(&net_device->refcnt); -} static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) { @@ -268,7 +260,6 @@ cleanup: netvsc_destroy_recv_buf(net_device); exit: - put_net_device(device); return ret; } @@ -349,7 +340,6 @@ static int netvsc_connect_vsp(struct hv_device *device) ret = netvsc_init_recv_buf(device); cleanup: - put_net_device(device); return ret; } @@ -368,7 +358,6 @@ int netvsc_device_remove(struct hv_device *device) unsigned long flags; net_device = (struct netvsc_device *)device->ext; - atomic_dec(&net_device->refcnt); spin_lock_irqsave(&device->channel->inbound_lock, flags); net_device->destroy = true; spin_unlock_irqrestore(&device->channel->inbound_lock, flags); @@ -383,19 +372,17 @@ int netvsc_device_remove(struct hv_device *device) netvsc_disconnect_vsp(net_device); - atomic_dec(&net_device->refcnt); - device->ext = NULL; /* - * Wait until the ref cnt falls to 0. - * We have already stopped any new references - * for outgoing traffic. Also, at this point we don't have any - * incoming traffic as well. So this must be outgoing refrences - * established prior to marking the device as being destroyed. - * Since the send path is non-blocking, it is reasonable to busy - * wait here. + * Since we have already drained, we don't need to busy wait + * as was done in final_release_stor_device() + * Note that we cannot set the ext pointer to NULL until + * we have drained - to drain the outgoing packets, we need to + * allow incoming packets. */ - while (atomic_read(&net_device->refcnt)) - udelay(100); + + spin_lock_irqsave(&device->channel->inbound_lock, flags); + device->ext = NULL; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* At this point, no one should be accessing netDevice except in here */ dev_notice(&device->device, "net device safe to remove"); @@ -456,7 +443,6 @@ static void netvsc_send_completion(struct hv_device *device, "%d received!!", nvsp_packet->hdr.msg_type); } - put_net_device(device); } int netvsc_send(struct hv_device *device, @@ -509,7 +495,6 @@ int netvsc_send(struct hv_device *device, packet, ret); atomic_inc(&net_device->num_outstanding_sends); - put_net_device(device); return ret; } @@ -602,7 +587,6 @@ static void netvsc_receive_completion(void *context) if (fsend_receive_comp) netvsc_send_recv_completion(device, transaction_id); - put_net_device(device); } static void netvsc_receive(struct hv_device *device, @@ -636,7 +620,6 @@ static void netvsc_receive(struct hv_device *device, if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { dev_err(&device->device, "Unknown packet type received - %d", packet->type); - put_net_device(device); return; } @@ -648,7 +631,6 @@ static void netvsc_receive(struct hv_device *device, NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { dev_err(&device->device, "Unknown nvsp packet type received-" " %d", nvsp_packet->hdr.msg_type); - put_net_device(device); return; } @@ -658,7 +640,6 @@ static void netvsc_receive(struct hv_device *device, dev_err(&device->device, "Invalid xfer page set id - " "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpage_packet->xfer_pageset_id); - put_net_device(device); return; } @@ -698,7 +679,6 @@ static void netvsc_receive(struct hv_device *device, netvsc_send_recv_completion(device, vmxferpage_packet->d.trans_id); - put_net_device(device); return; } @@ -786,7 +766,6 @@ static void netvsc_receive(struct hv_device *device, completion.recv.recv_completion_ctx); } - put_net_device(device); } static void netvsc_channel_cb(void *context) @@ -869,7 +848,6 @@ static void netvsc_channel_cb(void *context) } } while (1); - put_net_device(device); out: kfree(buffer); return; -- cgit v1.1 From bd1f5d6a0098debce610dc23729ebff691a5c3f5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:17 -0700 Subject: Staging: hv: storvsc: Add code to handle IDE devices using the storvsc driver Add code to handle IDE devices using the storvsc driver. The storvsc_probe() is modified so that the storvsc driver can surface all disks presented to the guest as scsi devices using generic upper level Linux scsi drivers. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 60 ++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ae74f50..f434200 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -59,6 +59,17 @@ struct storvsc_cmd_request { struct hv_storvsc_request request; }; +static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path) +{ + *target = + dev->dev_instance.b[5] << 8 | dev->dev_instance.b[4]; + + *path = + dev->dev_instance.b[3] << 24 | + dev->dev_instance.b[2] << 16 | + dev->dev_instance.b[1] << 8 | dev->dev_instance.b[0]; +} + static int storvsc_device_alloc(struct scsi_device *sdevice) { @@ -642,6 +653,20 @@ static const struct hv_vmbus_device_id id_table[] = { }; MODULE_DEVICE_TABLE(vmbus, id_table); + +/* + * This declaration is temporary; once we get the + * infrastructure in place, we will integrate with + * id_table. + */ + +static const uuid_le ide_blk_guid = { + .b = { + 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 + } +}; + /* * storvsc_probe - Add a new device for this driver */ @@ -652,6 +677,14 @@ static int storvsc_probe(struct hv_device *device) struct Scsi_Host *host; struct hv_host_device *host_dev; struct storvsc_device_info device_info; + bool dev_is_ide; + int path = 0; + int target = 0; + + if (!uuid_le_cmp(device->dev_type, ide_blk_guid)) + dev_is_ide = true; + else + dev_is_ide = false; host = scsi_host_alloc(&scsi_driver, sizeof(struct hv_host_device)); @@ -687,6 +720,9 @@ static int storvsc_probe(struct hv_device *device) return -ENODEV; } + if (dev_is_ide) + storvsc_get_ide_info(device, &target, &path); + host_dev->path = device_info.path_id; host_dev->target = device_info.target_id; @@ -699,17 +735,25 @@ static int storvsc_probe(struct hv_device *device) /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); - if (ret != 0) { - - storvsc_dev_remove(device); + if (ret != 0) + goto err_out; - kmem_cache_destroy(host_dev->request_pool); - scsi_host_put(host); - return -ENODEV; + if (!dev_is_ide) { + scsi_scan_host(host); + return 0; + } + ret = scsi_add_device(host, 0, target, 0); + if (ret) { + scsi_remove_host(host); + goto err_out; } + return 0; - scsi_scan_host(host); - return ret; +err_out: + storvsc_dev_remove(device); + kmem_cache_destroy(host_dev->request_pool); + scsi_host_put(host); + return -ENODEV; } /* The one and only one */ -- cgit v1.1 From 21e37742361fe408d534c004b6e39717cb6b5999 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:18 -0700 Subject: Staging: hv: storvsc: Handle IDE devices using the storvsc driver Now, enable handling of all IDE devices by extending the storvsc device id table to handle IDE guid. As part of this cleanup Kconfig and Hyper-V Makefile to not build the IDE driver (blkvsc). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Kconfig | 7 ------- drivers/staging/hv/Makefile | 2 -- drivers/staging/hv/storvsc_drv.c | 21 ++++++++------------- 3 files changed, 8 insertions(+), 22 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig index 5e0c9f6..26b5064 100644 --- a/drivers/staging/hv/Kconfig +++ b/drivers/staging/hv/Kconfig @@ -15,13 +15,6 @@ config HYPERV_STORAGE help Select this option to enable the Hyper-V virtual storage driver. -config HYPERV_BLOCK - tristate "Microsoft Hyper-V virtual block driver" - depends on BLOCK && SCSI && (LBDAF || 64BIT) - default HYPERV - help - Select this option to enable the Hyper-V virtual block driver. - config HYPERV_NET tristate "Microsoft Hyper-V virtual network driver" depends on NET diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile index 3004674..bb89437 100644 --- a/drivers/staging/hv/Makefile +++ b/drivers/staging/hv/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_HYPERV) += hv_vmbus.o hv_timesource.o obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o -obj-$(CONFIG_HYPERV_BLOCK) += hv_blkvsc.o obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o @@ -9,6 +8,5 @@ hv_vmbus-y := vmbus_drv.o \ hv.o connection.o channel.o \ channel_mgmt.o ring_buffer.o hv_storvsc-y := storvsc_drv.o storvsc.o -hv_blkvsc-y := blkvsc_drv.o storvsc.o hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o hv_utils-y := hv_util.o hv_kvp.o diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index f434200..9464f99 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -645,27 +645,22 @@ static struct scsi_host_template scsi_driver = { .dma_boundary = PAGE_SIZE-1, }; +/* + * The storvsc_probe function assumes that the IDE guid + * is the second entry. + */ static const struct hv_vmbus_device_id id_table[] = { /* SCSI guid */ { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) }, + /* IDE guid */ + { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) }, { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); -/* - * This declaration is temporary; once we get the - * infrastructure in place, we will integrate with - * id_table. - */ - -static const uuid_le ide_blk_guid = { - .b = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } -}; /* * storvsc_probe - Add a new device for this driver @@ -681,7 +676,7 @@ static int storvsc_probe(struct hv_device *device) int path = 0; int target = 0; - if (!uuid_le_cmp(device->dev_type, ide_blk_guid)) + if (!memcmp(&device->dev_type.b, id_table[1].guid, sizeof(uuid_le))) dev_is_ide = true; else dev_is_ide = false; -- cgit v1.1 From b38cc43432d7b7b0a4dc0a13d261a85944fc7c65 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:19 -0700 Subject: Staging: hv: blkvsc: Get rid of blkvsc_drv.c as this code is not used Now that blkvsc driver is no longer needed, remove blkvsc_drv.c Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 1014 --------------------------------------- 1 file changed, 1014 deletions(-) delete mode 100644 drivers/staging/hv/blkvsc_drv.c (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c deleted file mode 100644 index 2b41eb6..0000000 --- a/drivers/staging/hv/blkvsc_drv.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_storage.h" - - -#define BLKVSC_MINORS 64 - -enum blkvsc_device_type { - UNKNOWN_DEV_TYPE, - HARDDISK_TYPE, - DVD_TYPE, -}; - -enum blkvsc_op_type { - DO_INQUIRY, - DO_CAPACITY, - DO_FLUSH, -}; - -/* - * This request ties the struct request and struct - * blkvsc_request/hv_storvsc_request together A struct request may be - * represented by 1 or more struct blkvsc_request - */ -struct blkvsc_request_group { - int outstanding; - int status; - struct list_head blkvsc_req_list; /* list of blkvsc_requests */ -}; - -struct blkvsc_request { - /* blkvsc_request_group.blkvsc_req_list */ - struct list_head req_entry; - - /* block_device_context.pending_list */ - struct list_head pend_entry; - - /* This may be null if we generate a request internally */ - struct request *req; - - struct block_device_context *dev; - - /* The group this request is part of. Maybe null */ - struct blkvsc_request_group *group; - - int write; - sector_t sector_start; - unsigned long sector_count; - - unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; - unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; - - struct hv_storvsc_request request; -}; - -/* Per device structure */ -struct block_device_context { - /* point back to our device context */ - struct hv_device *device_ctx; - struct kmem_cache *request_pool; - spinlock_t lock; - struct gendisk *gd; - enum blkvsc_device_type device_type; - struct list_head pending_list; - - unsigned char device_id[64]; - unsigned int device_id_len; - int num_outstanding_reqs; - int shutting_down; - unsigned int sector_size; - sector_t capacity; - unsigned int port; - unsigned char path; - unsigned char target; - int users; -}; - - -/* - * There is a circular dependency involving blkvsc_request_completion() - * and blkvsc_do_request(). - */ -static void blkvsc_request_completion(struct hv_storvsc_request *request); - -static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE; - -module_param(blkvsc_ringbuffer_size, int, S_IRUGO); -MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)"); - -/* - * There is a circular dependency involving blkvsc_probe() - * and block_ops. - */ -static int blkvsc_probe(struct hv_device *dev); - -static int blkvsc_device_add(struct hv_device *device, - void *additional_info) -{ - struct storvsc_device_info *device_info; - int ret = 0; - - device_info = (struct storvsc_device_info *)additional_info; - - device_info->ring_buffer_size = blkvsc_ringbuffer_size; - - ret = storvsc_dev_add(device, additional_info); - if (ret != 0) - return ret; - - /* - * We need to use the device instance guid to set the path and target - * id. For IDE devices, the device instance id is formatted as - * * - - 8899 - 000000000000. - */ - device_info->path_id = device->dev_instance.b[3] << 24 | - device->dev_instance.b[2] << 16 | - device->dev_instance.b[1] << 8 | - device->dev_instance.b[0]; - - device_info->target_id = device->dev_instance.b[5] << 8 | - device->dev_instance.b[4]; - - return ret; -} - -static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, - void (*request_completion)(struct hv_storvsc_request *)) -{ - struct block_device_context *blkdev = blkvsc_req->dev; - struct hv_storvsc_request *storvsc_req; - struct vmscsi_request *vm_srb; - int ret; - - - storvsc_req = &blkvsc_req->request; - vm_srb = &storvsc_req->vstor_packet.vm_srb; - - vm_srb->data_in = blkvsc_req->write ? WRITE_TYPE : READ_TYPE; - - storvsc_req->on_io_completion = request_completion; - storvsc_req->context = blkvsc_req; - - vm_srb->port_number = blkdev->port; - vm_srb->path_id = blkdev->path; - vm_srb->target_id = blkdev->target; - vm_srb->lun = 0; /* this is not really used at all */ - - vm_srb->cdb_length = blkvsc_req->cmd_len; - - memcpy(vm_srb->cdb, blkvsc_req->cmnd, vm_srb->cdb_length); - - storvsc_req->sense_buffer = blkvsc_req->sense_buffer; - - ret = storvsc_do_io(blkdev->device_ctx, - &blkvsc_req->request); - if (ret == 0) - blkdev->num_outstanding_reqs++; - - return ret; -} - - -static int blkvsc_open(struct block_device *bdev, fmode_t mode) -{ - struct block_device_context *blkdev = bdev->bd_disk->private_data; - unsigned long flags; - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->users++; - - spin_unlock_irqrestore(&blkdev->lock, flags); - - return 0; -} - - -static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg) -{ - sector_t nsect = get_capacity(bd->bd_disk); - sector_t cylinders = nsect; - - /* - * We are making up these values; let us keep it simple. - */ - hg->heads = 0xff; - hg->sectors = 0x3f; - sector_div(cylinders, hg->heads * hg->sectors); - hg->cylinders = cylinders; - if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) - hg->cylinders = 0xffff; - return 0; - -} - - -static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) -{ - - blkvsc_req->cmd_len = 16; - - if (rq_data_dir(blkvsc_req->req)) { - blkvsc_req->write = 1; - blkvsc_req->cmnd[0] = WRITE_16; - } else { - blkvsc_req->write = 0; - blkvsc_req->cmnd[0] = READ_16; - } - - blkvsc_req->cmnd[1] |= - (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; - - *(unsigned long long *)&blkvsc_req->cmnd[2] = - cpu_to_be64(blkvsc_req->sector_start); - *(unsigned int *)&blkvsc_req->cmnd[10] = - cpu_to_be32(blkvsc_req->sector_count); -} - - -static int blkvsc_ioctl(struct block_device *bd, fmode_t mode, - unsigned cmd, unsigned long arg) -{ - struct block_device_context *blkdev = bd->bd_disk->private_data; - int ret = 0; - - switch (cmd) { - case HDIO_GET_IDENTITY: - if (copy_to_user((void __user *)arg, blkdev->device_id, - blkdev->device_id_len)) - ret = -EFAULT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static void blkvsc_cmd_completion(struct hv_storvsc_request *request) -{ - struct blkvsc_request *blkvsc_req = - (struct blkvsc_request *)request->context; - struct block_device_context *blkdev = - (struct block_device_context *)blkvsc_req->dev; - struct scsi_sense_hdr sense_hdr; - struct vmscsi_request *vm_srb; - unsigned long flags; - - - vm_srb = &blkvsc_req->request.vstor_packet.vm_srb; - - spin_lock_irqsave(&blkdev->lock, flags); - blkdev->num_outstanding_reqs--; - spin_unlock_irqrestore(&blkdev->lock, flags); - - if (vm_srb->scsi_status) - if (scsi_normalize_sense(blkvsc_req->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr)) - scsi_print_sense_hdr("blkvsc", &sense_hdr); - - complete(&blkvsc_req->request.wait_event); -} - - -static int blkvsc_do_operation(struct block_device_context *blkdev, - enum blkvsc_op_type op) -{ - struct blkvsc_request *blkvsc_req; - struct page *page_buf; - unsigned char *buf; - unsigned char device_type; - struct scsi_sense_hdr sense_hdr; - struct vmscsi_request *vm_srb; - unsigned long flags; - - int ret = 0; - - blkvsc_req = kmem_cache_zalloc(blkdev->request_pool, GFP_KERNEL); - if (!blkvsc_req) - return -ENOMEM; - - page_buf = alloc_page(GFP_KERNEL); - if (!page_buf) { - kmem_cache_free(blkdev->request_pool, blkvsc_req); - return -ENOMEM; - } - - vm_srb = &blkvsc_req->request.vstor_packet.vm_srb; - init_completion(&blkvsc_req->request.wait_event); - blkvsc_req->dev = blkdev; - blkvsc_req->req = NULL; - blkvsc_req->write = 0; - - blkvsc_req->request.data_buffer.pfn_array[0] = - page_to_pfn(page_buf); - blkvsc_req->request.data_buffer.offset = 0; - - switch (op) { - case DO_INQUIRY: - blkvsc_req->cmnd[0] = INQUIRY; - blkvsc_req->cmnd[1] = 0x1; /* Get product data */ - blkvsc_req->cmnd[2] = 0x83; /* mode page 83 */ - blkvsc_req->cmnd[4] = 64; - blkvsc_req->cmd_len = 6; - blkvsc_req->request.data_buffer.len = 64; - break; - - case DO_CAPACITY: - blkdev->sector_size = 0; - blkdev->capacity = 0; - - blkvsc_req->cmnd[0] = READ_CAPACITY; - blkvsc_req->cmd_len = 16; - blkvsc_req->request.data_buffer.len = 8; - break; - - case DO_FLUSH: - blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE; - blkvsc_req->cmd_len = 10; - blkvsc_req->request.data_buffer.pfn_array[0] = 0; - blkvsc_req->request.data_buffer.len = 0; - break; - default: - ret = -EINVAL; - goto cleanup; - } - - spin_lock_irqsave(&blkdev->lock, flags); - blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion); - spin_unlock_irqrestore(&blkdev->lock, flags); - - wait_for_completion_interruptible(&blkvsc_req->request.wait_event); - - /* check error */ - if (vm_srb->scsi_status) { - scsi_normalize_sense(blkvsc_req->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr); - - return 0; - } - - buf = kmap(page_buf); - - switch (op) { - case DO_INQUIRY: - device_type = buf[0] & 0x1F; - - if (device_type == 0x0) - blkdev->device_type = HARDDISK_TYPE; - else - blkdev->device_type = UNKNOWN_DEV_TYPE; - - blkdev->device_id_len = buf[7]; - if (blkdev->device_id_len > 64) - blkdev->device_id_len = 64; - - memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len); - break; - - case DO_CAPACITY: - /* be to le */ - blkdev->capacity = - ((buf[0] << 24) | (buf[1] << 16) | - (buf[2] << 8) | buf[3]) + 1; - - blkdev->sector_size = - (buf[4] << 24) | (buf[5] << 16) | - (buf[6] << 8) | buf[7]; - break; - default: - break; - - } - -cleanup: - - kunmap(page_buf); - - __free_page(page_buf); - - kmem_cache_free(blkdev->request_pool, blkvsc_req); - - return ret; -} - - -static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev) -{ - struct blkvsc_request *pend_req, *tmp; - struct blkvsc_request *comp_req, *tmp2; - struct vmscsi_request *vm_srb; - - int ret = 0; - - - /* Flush the pending list first */ - list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, - pend_entry) { - /* - * The pend_req could be part of a partially completed - * request. If so, complete those req first until we - * hit the pend_req - */ - list_for_each_entry_safe(comp_req, tmp2, - &pend_req->group->blkvsc_req_list, - req_entry) { - - if (comp_req == pend_req) - break; - - list_del(&comp_req->req_entry); - - if (comp_req->req) { - vm_srb = - &comp_req->request.vstor_packet. - vm_srb; - ret = __blk_end_request(comp_req->req, - (!vm_srb->scsi_status ? 0 : -EIO), - comp_req->sector_count * - blkdev->sector_size); - - /* FIXME: shouldn't this do more than return? */ - if (ret) - goto out; - } - - kmem_cache_free(blkdev->request_pool, comp_req); - } - - list_del(&pend_req->pend_entry); - - list_del(&pend_req->req_entry); - - if (comp_req->req) { - if (!__blk_end_request(pend_req->req, -EIO, - pend_req->sector_count * - blkdev->sector_size)) { - /* - * All the sectors have been xferred ie the - * request is done - */ - kmem_cache_free(blkdev->request_pool, - pend_req->group); - } - } - - kmem_cache_free(blkdev->request_pool, pend_req); - } - -out: - return ret; -} - - -/* - * blkvsc_remove() - Callback when our device is removed - */ -static int blkvsc_remove(struct hv_device *dev) -{ - struct block_device_context *blkdev = dev_get_drvdata(&dev->device); - unsigned long flags; - - - /* Get to a known state */ - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->shutting_down = 1; - - blk_stop_queue(blkdev->gd->queue); - - blkvsc_cancel_pending_reqs(blkdev); - - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - - if (blkdev->users == 0) { - del_gendisk(blkdev->gd); - put_disk(blkdev->gd); - blk_cleanup_queue(blkdev->gd->queue); - - storvsc_dev_remove(blkdev->device_ctx); - - kmem_cache_destroy(blkdev->request_pool); - kfree(blkdev); - } - - return 0; -} - -static void blkvsc_shutdown(struct hv_device *dev) -{ - struct block_device_context *blkdev = dev_get_drvdata(&dev->device); - unsigned long flags; - - if (!blkdev) - return; - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->shutting_down = 1; - - blk_stop_queue(blkdev->gd->queue); - - blkvsc_cancel_pending_reqs(blkdev); - - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - - /* - * Now wait for all outgoing I/O to be drained. - */ - storvsc_wait_to_drain((struct storvsc_device *)dev->ext); - -} - -static int blkvsc_release(struct gendisk *disk, fmode_t mode) -{ - struct block_device_context *blkdev = disk->private_data; - unsigned long flags; - - spin_lock_irqsave(&blkdev->lock, flags); - - if ((--blkdev->users == 0) && (blkdev->shutting_down)) { - blk_stop_queue(blkdev->gd->queue); - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - del_gendisk(blkdev->gd); - put_disk(blkdev->gd); - blk_cleanup_queue(blkdev->gd->queue); - - storvsc_dev_remove(blkdev->device_ctx); - - kmem_cache_destroy(blkdev->request_pool); - kfree(blkdev); - } else - spin_unlock_irqrestore(&blkdev->lock, flags); - - return 0; -} - - -/* - * We break the request into 1 or more blkvsc_requests and submit - * them. If we cant submit them all, we put them on the - * pending_list. The blkvsc_request() will work on the pending_list. - */ -static int blkvsc_do_request(struct block_device_context *blkdev, - struct request *req) -{ - struct bio *bio = NULL; - struct bio_vec *bvec = NULL; - struct bio_vec *prev_bvec = NULL; - struct blkvsc_request *blkvsc_req = NULL; - struct blkvsc_request *tmp; - int databuf_idx = 0; - int seg_idx = 0; - sector_t start_sector; - unsigned long num_sectors = 0; - int ret = 0; - int pending = 0; - struct blkvsc_request_group *group = NULL; - - /* Create a group to tie req to list of blkvsc_reqs */ - group = kmem_cache_zalloc(blkdev->request_pool, GFP_ATOMIC); - if (!group) - return -ENOMEM; - - INIT_LIST_HEAD(&group->blkvsc_req_list); - group->outstanding = group->status = 0; - - start_sector = blk_rq_pos(req); - - /* foreach bio in the request */ - if (req->bio) { - for (bio = req->bio; bio; bio = bio->bi_next) { - /* - * Map this bio into an existing or new storvsc request - */ - bio_for_each_segment(bvec, bio, seg_idx) { - /* Get a new storvsc request */ - /* 1st-time */ - if ((!blkvsc_req) || - (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT) - /* hole at the begin of page */ - || (bvec->bv_offset != 0) || - /* hold at the end of page */ - (prev_bvec && - (prev_bvec->bv_len != PAGE_SIZE))) { - /* submit the prev one */ - if (blkvsc_req) { - blkvsc_req->sector_start = - start_sector; - sector_div( - blkvsc_req->sector_start, - (blkdev->sector_size >> 9)); - - blkvsc_req->sector_count = - num_sectors / - (blkdev->sector_size >> 9); - blkvsc_init_rw(blkvsc_req); - } - - /* - * Create new blkvsc_req to represent - * the current bvec - */ - blkvsc_req = - kmem_cache_zalloc( - blkdev->request_pool, GFP_ATOMIC); - if (!blkvsc_req) { - /* free up everything */ - list_for_each_entry_safe( - blkvsc_req, tmp, - &group->blkvsc_req_list, - req_entry) { - list_del( - &blkvsc_req->req_entry); - kmem_cache_free( - blkdev->request_pool, - blkvsc_req); - } - - kmem_cache_free( - blkdev->request_pool, group); - return -ENOMEM; - } - - memset(blkvsc_req, 0, - sizeof(struct blkvsc_request)); - - blkvsc_req->dev = blkdev; - blkvsc_req->req = req; - blkvsc_req->request. - data_buffer.offset - = bvec->bv_offset; - blkvsc_req->request. - data_buffer.len = 0; - - /* Add to the group */ - blkvsc_req->group = group; - blkvsc_req->group->outstanding++; - list_add_tail(&blkvsc_req->req_entry, - &blkvsc_req->group->blkvsc_req_list); - - start_sector += num_sectors; - num_sectors = 0; - databuf_idx = 0; - } - - /* - * Add the curr bvec/segment to the curr - * blkvsc_req - */ - blkvsc_req->request.data_buffer. - pfn_array[databuf_idx] - = page_to_pfn(bvec->bv_page); - blkvsc_req->request.data_buffer.len - += bvec->bv_len; - - prev_bvec = bvec; - - databuf_idx++; - num_sectors += bvec->bv_len >> 9; - - } /* bio_for_each_segment */ - - } /* rq_for_each_bio */ - } - - /* Handle the last one */ - if (blkvsc_req) { - blkvsc_req->sector_start = start_sector; - sector_div(blkvsc_req->sector_start, - (blkdev->sector_size >> 9)); - - blkvsc_req->sector_count = num_sectors / - (blkdev->sector_size >> 9); - - blkvsc_init_rw(blkvsc_req); - } - - list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) { - if (pending) { - - list_add_tail(&blkvsc_req->pend_entry, - &blkdev->pending_list); - } else { - ret = blkvsc_submit_request(blkvsc_req, - blkvsc_request_completion); - if (ret == -EAGAIN) { - pending = 1; - list_add_tail(&blkvsc_req->pend_entry, - &blkdev->pending_list); - } - - } - } - - return pending; -} - -static int blkvsc_do_pending_reqs(struct block_device_context *blkdev) -{ - struct blkvsc_request *pend_req, *tmp; - int ret = 0; - - /* Flush the pending list first */ - list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, - pend_entry) { - - ret = blkvsc_submit_request(pend_req, - blkvsc_request_completion); - if (ret != 0) - break; - else - list_del(&pend_req->pend_entry); - } - - return ret; -} - - -static void blkvsc_request(struct request_queue *queue) -{ - struct block_device_context *blkdev = NULL; - struct request *req; - int ret = 0; - - while ((req = blk_peek_request(queue)) != NULL) { - - blkdev = req->rq_disk->private_data; - if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS) { - __blk_end_request_cur(req, 0); - continue; - } - - ret = blkvsc_do_pending_reqs(blkdev); - - if (ret != 0) { - blk_stop_queue(queue); - break; - } - - blk_start_request(req); - - ret = blkvsc_do_request(blkdev, req); - if (ret > 0) { - blk_stop_queue(queue); - break; - } else if (ret < 0) { - blk_requeue_request(queue, req); - blk_stop_queue(queue); - break; - } - } -} - -static const struct hv_vmbus_device_id id_table[] = { - /* IDE guid */ - { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) }, - { }, -}; - -MODULE_DEVICE_TABLE(vmbus, id_table); - -/* The one and only one */ -static struct hv_driver blkvsc_drv = { - .name = "blkvsc", - .id_table = id_table, - .probe = blkvsc_probe, - .remove = blkvsc_remove, - .shutdown = blkvsc_shutdown, -}; - -static const struct block_device_operations block_ops = { - .owner = THIS_MODULE, - .open = blkvsc_open, - .release = blkvsc_release, - .getgeo = blkvsc_getgeo, - .ioctl = blkvsc_ioctl, -}; - -/* - * blkvsc_drv_init - BlkVsc driver initialization. - */ -static int blkvsc_drv_init(void) -{ - BUILD_BUG_ON(sizeof(sector_t) != 8); - return vmbus_driver_register(&blkvsc_drv); -} - -static void blkvsc_drv_exit(void) -{ - vmbus_driver_unregister(&blkvsc_drv); -} - -/* - * blkvsc_probe - Add a new device for this driver - */ -static int blkvsc_probe(struct hv_device *dev) -{ - struct block_device_context *blkdev = NULL; - struct storvsc_device_info device_info; - struct storvsc_major_info major_info; - int ret = 0; - - blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL); - if (!blkdev) { - ret = -ENOMEM; - goto cleanup; - } - - INIT_LIST_HEAD(&blkdev->pending_list); - - /* Initialize what we can here */ - spin_lock_init(&blkdev->lock); - - - blkdev->request_pool = kmem_cache_create(dev_name(&dev->device), - sizeof(struct blkvsc_request), 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!blkdev->request_pool) { - ret = -ENOMEM; - goto cleanup; - } - - - ret = blkvsc_device_add(dev, &device_info); - if (ret != 0) - goto cleanup; - - blkdev->device_ctx = dev; - /* this identified the device 0 or 1 */ - blkdev->target = device_info.target_id; - /* this identified the ide ctrl 0 or 1 */ - blkdev->path = device_info.path_id; - - dev_set_drvdata(&dev->device, blkdev); - - ret = storvsc_get_major_info(&device_info, &major_info); - - if (ret) - goto cleanup; - - if (major_info.do_register) { - ret = register_blkdev(major_info.major, major_info.devname); - - if (ret != 0) { - DPRINT_ERR(BLKVSC_DRV, - "register_blkdev() failed! ret %d", ret); - goto remove; - } - } - - DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!", - major_info.major); - - blkdev->gd = alloc_disk(BLKVSC_MINORS); - if (!blkdev->gd) { - ret = -1; - goto cleanup; - } - - blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock); - - blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE); - blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT); - blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1); - blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY); - blk_queue_dma_alignment(blkdev->gd->queue, 511); - - blkdev->gd->major = major_info.major; - if (major_info.index == 1 || major_info.index == 3) - blkdev->gd->first_minor = BLKVSC_MINORS; - else - blkdev->gd->first_minor = 0; - blkdev->gd->fops = &block_ops; - blkdev->gd->private_data = blkdev; - blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); - sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index); - - blkvsc_do_operation(blkdev, DO_INQUIRY); - blkvsc_do_operation(blkdev, DO_CAPACITY); - - set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512)); - blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size); - /* go! */ - add_disk(blkdev->gd); - - DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d", - blkdev->gd->disk_name, (unsigned long)blkdev->capacity, - blkdev->sector_size); - - return ret; - -remove: - storvsc_dev_remove(dev); - -cleanup: - if (blkdev) { - if (blkdev->request_pool) { - kmem_cache_destroy(blkdev->request_pool); - blkdev->request_pool = NULL; - } - kfree(blkdev); - blkdev = NULL; - } - - return ret; -} - -static void blkvsc_request_completion(struct hv_storvsc_request *request) -{ - struct blkvsc_request *blkvsc_req = - (struct blkvsc_request *)request->context; - struct block_device_context *blkdev = - (struct block_device_context *)blkvsc_req->dev; - unsigned long flags; - struct blkvsc_request *comp_req, *tmp; - struct vmscsi_request *vm_srb; - - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->num_outstanding_reqs--; - blkvsc_req->group->outstanding--; - - /* - * Only start processing when all the blkvsc_reqs are - * completed. This guarantees no out-of-order blkvsc_req - * completion when calling end_that_request_first() - */ - if (blkvsc_req->group->outstanding == 0) { - list_for_each_entry_safe(comp_req, tmp, - &blkvsc_req->group->blkvsc_req_list, - req_entry) { - - list_del(&comp_req->req_entry); - - vm_srb = - &comp_req->request.vstor_packet.vm_srb; - if (!__blk_end_request(comp_req->req, - (!vm_srb->scsi_status ? 0 : -EIO), - comp_req->sector_count * blkdev->sector_size)) { - /* - * All the sectors have been xferred ie the - * request is done - */ - kmem_cache_free(blkdev->request_pool, - comp_req->group); - } - - kmem_cache_free(blkdev->request_pool, comp_req); - } - - if (!blkdev->shutting_down) { - blkvsc_do_pending_reqs(blkdev); - blk_start_queue(blkdev->gd->queue); - blkvsc_request(blkdev->gd->queue); - } - } - - spin_unlock_irqrestore(&blkdev->lock, flags); -} - -static void __exit blkvsc_exit(void) -{ - blkvsc_drv_exit(); -} - -MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); -MODULE_DESCRIPTION("Microsoft Hyper-V virtual block driver"); -module_init(blkvsc_drv_init); -module_exit(blkvsc_exit); -- cgit v1.1 From 3612ef99b05f107d5cd85f6bc45b94ed880d78f3 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:20 -0700 Subject: Staging: hv: storvsc: Optimize bounce buffer handling for the "write" case Optimize bounce buffer handling for the "write" case. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 9464f99..90b91ad 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -425,17 +425,17 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request) struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; + vm_srb = &request->vstor_packet.vm_srb; if (cmd_request->bounce_sgl_count) { - - /* FIXME: We can optimize on writes by just skipping this */ - copy_from_bounce_buffer(scsi_sglist(scmnd), + if (vm_srb->data_in == READ_TYPE) { + copy_from_bounce_buffer(scsi_sglist(scmnd), cmd_request->bounce_sgl, scsi_sg_count(scmnd)); - destroy_bounce_buffer(cmd_request->bounce_sgl, - cmd_request->bounce_sgl_count); + destroy_bounce_buffer(cmd_request->bounce_sgl, + cmd_request->bounce_sgl_count); + } } - vm_srb = &request->vstor_packet.vm_srb; scmnd->result = vm_srb->scsi_status; if (scmnd->result) { -- cgit v1.1 From fa23b8c78fefae4e8033a28e685673c35ff10789 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:21 -0700 Subject: Staging: hv: storvsc: Optimize the bounce buffer handling in the "read" case Optimize the bounce buffer handling in the "read" case. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 90b91ad..3e00e70 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -560,12 +560,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >> PAGE_SHIFT; - /* - * FIXME: We can optimize on reads by just skipping - * this - */ - copy_to_bounce_buffer(sgl, cmd_request->bounce_sgl, - scsi_sg_count(scmnd)); + if (vm_srb->data_in == WRITE_TYPE) + copy_to_bounce_buffer(sgl, + cmd_request->bounce_sgl, + scsi_sg_count(scmnd)); sgl = cmd_request->bounce_sgl; sg_count = cmd_request->bounce_sgl_count; -- cgit v1.1 From 8dcf37d446f103d55b96beddb100db6a0ad8d0ba Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:22 -0700 Subject: Staging: hv: storvsc: Include storvsc.c in storvsc_drv.c As part of further cleanup of our storage drivers, include the content of storvsc.c into storvsc_drv.c and delete storvsc.c and do the necessary adjustments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Makefile | 2 +- drivers/staging/hv/storvsc.c | 528 -------------------------------------- drivers/staging/hv/storvsc_drv.c | 529 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 530 insertions(+), 529 deletions(-) delete mode 100644 drivers/staging/hv/storvsc.c (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile index bb89437..bd176b1 100644 --- a/drivers/staging/hv/Makefile +++ b/drivers/staging/hv/Makefile @@ -7,6 +7,6 @@ obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o hv_vmbus-y := vmbus_drv.o \ hv.o connection.o channel.o \ channel_mgmt.o ring_buffer.o -hv_storvsc-y := storvsc_drv.o storvsc.o +hv_storvsc-y := storvsc_drv.o hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o hv_utils-y := hv_util.o hv_kvp.o diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c deleted file mode 100644 index fb7b3ca..0000000 --- a/drivers/staging/hv/storvsc.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_storage.h" - - -static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); - if (!stor_device) - return NULL; - - stor_device->destroy = false; - init_waitqueue_head(&stor_device->waiting_to_drain); - stor_device->device = device; - device->ext = stor_device; - - return stor_device; -} - - -static inline struct storvsc_device *get_in_stor_device( - struct hv_device *device) -{ - struct storvsc_device *stor_device; - unsigned long flags; - - spin_lock_irqsave(&device->channel->inbound_lock, flags); - stor_device = (struct storvsc_device *)device->ext; - - if (!stor_device) - goto get_in_err; - - /* - * If the device is being destroyed; allow incoming - * traffic only to cleanup outstanding requests. - */ - - if (stor_device->destroy && - (atomic_read(&stor_device->num_outstanding_req) == 0)) - stor_device = NULL; - -get_in_err: - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - return stor_device; - -} - -static int storvsc_channel_init(struct hv_device *device) -{ - struct storvsc_device *stor_device; - struct hv_storvsc_request *request; - struct vstor_packet *vstor_packet; - int ret, t; - - stor_device = get_out_stor_device(device); - if (!stor_device) - return -ENODEV; - - request = &stor_device->init_request; - vstor_packet = &request->vstor_packet; - - /* - * Now, initiate the vsc/vsp initialization protocol on the open - * channel - */ - memset(request, 0, sizeof(struct hv_storvsc_request)); - init_completion(&request->wait_event); - vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) - goto cleanup; - - - /* reuse the packet for version range supported */ - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; - - vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT; - FILL_VMSTOR_REVISION(vstor_packet->version.revision); - - ret = vmbus_sendpacket(device->channel, vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) - goto cleanup; - - - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->storage_channel_properties.port_number = - stor_device->port_number; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) - goto cleanup; - - stor_device->path_id = vstor_packet->storage_channel_properties.path_id; - stor_device->target_id - = vstor_packet->storage_channel_properties.target_id; - - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) - goto cleanup; - - -cleanup: - return ret; -} - -static void storvsc_on_io_completion(struct hv_device *device, - struct vstor_packet *vstor_packet, - struct hv_storvsc_request *request) -{ - struct storvsc_device *stor_device; - struct vstor_packet *stor_pkt; - - stor_device = (struct storvsc_device *)device->ext; - - stor_pkt = &request->vstor_packet; - - - /* Copy over the status...etc */ - stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; - stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; - stor_pkt->vm_srb.sense_info_length = - vstor_packet->vm_srb.sense_info_length; - - if (vstor_packet->vm_srb.scsi_status != 0 || - vstor_packet->vm_srb.srb_status != 1){ - DPRINT_WARN(STORVSC, - "cmd 0x%x scsi status 0x%x srb status 0x%x\n", - stor_pkt->vm_srb.cdb[0], - vstor_packet->vm_srb.scsi_status, - vstor_packet->vm_srb.srb_status); - } - - if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { - /* CHECK_CONDITION */ - if (vstor_packet->vm_srb.srb_status & 0x80) { - /* autosense data available */ - DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data " - "valid - len %d\n", request, - vstor_packet->vm_srb.sense_info_length); - - memcpy(request->sense_buffer, - vstor_packet->vm_srb.sense_data, - vstor_packet->vm_srb.sense_info_length); - - } - } - - stor_pkt->vm_srb.data_transfer_length = - vstor_packet->vm_srb.data_transfer_length; - - request->on_io_completion(request); - - if (atomic_dec_and_test(&stor_device->num_outstanding_req) && - stor_device->drain_notify) - wake_up(&stor_device->waiting_to_drain); - - -} - -static void storvsc_on_receive(struct hv_device *device, - struct vstor_packet *vstor_packet, - struct hv_storvsc_request *request) -{ - switch (vstor_packet->operation) { - case VSTOR_OPERATION_COMPLETE_IO: - storvsc_on_io_completion(device, vstor_packet, request); - break; - case VSTOR_OPERATION_REMOVE_DEVICE: - - default: - break; - } -} - -static void storvsc_on_channel_callback(void *context) -{ - struct hv_device *device = (struct hv_device *)context; - struct storvsc_device *stor_device; - u32 bytes_recvd; - u64 request_id; - unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)]; - struct hv_storvsc_request *request; - int ret; - - - stor_device = get_in_stor_device(device); - if (!stor_device) - return; - - do { - ret = vmbus_recvpacket(device->channel, packet, - ALIGN(sizeof(struct vstor_packet), 8), - &bytes_recvd, &request_id); - if (ret == 0 && bytes_recvd > 0) { - - request = (struct hv_storvsc_request *) - (unsigned long)request_id; - - if ((request == &stor_device->init_request) || - (request == &stor_device->reset_request)) { - - memcpy(&request->vstor_packet, packet, - sizeof(struct vstor_packet)); - complete(&request->wait_event); - } else { - storvsc_on_receive(device, - (struct vstor_packet *)packet, - request); - } - } else { - break; - } - } while (1); - - return; -} - -static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) -{ - struct vmstorage_channel_properties props; - int ret; - - memset(&props, 0, sizeof(struct vmstorage_channel_properties)); - - /* Open the channel */ - ret = vmbus_open(device->channel, - ring_size, - ring_size, - (void *)&props, - sizeof(struct vmstorage_channel_properties), - storvsc_on_channel_callback, device); - - if (ret != 0) - return ret; - - ret = storvsc_channel_init(device); - - return ret; -} - -int storvsc_dev_add(struct hv_device *device, - void *additional_info) -{ - struct storvsc_device *stor_device; - struct storvsc_device_info *device_info; - int ret = 0; - - device_info = (struct storvsc_device_info *)additional_info; - stor_device = alloc_stor_device(device); - if (!stor_device) - return -ENOMEM; - - /* Save the channel properties to our storvsc channel */ - - /* - * If we support more than 1 scsi channel, we need to set the - * port number here to the scsi channel but how do we get the - * scsi channel prior to the bus scan. - * - * The host does not support this. - */ - - stor_device->port_number = device_info->port_number; - /* Send it back up */ - ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size); - if (ret) { - kfree(stor_device); - return ret; - } - device_info->path_id = stor_device->path_id; - device_info->target_id = stor_device->target_id; - - return ret; -} - -int storvsc_dev_remove(struct hv_device *device) -{ - struct storvsc_device *stor_device; - unsigned long flags; - - stor_device = (struct storvsc_device *)device->ext; - - spin_lock_irqsave(&device->channel->inbound_lock, flags); - stor_device->destroy = true; - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - - /* - * At this point, all outbound traffic should be disable. We - * only allow inbound traffic (responses) to proceed so that - * outstanding requests can be completed. - */ - - storvsc_wait_to_drain(stor_device); - - /* - * Since we have already drained, we don't need to busy wait - * as was done in final_release_stor_device() - * Note that we cannot set the ext pointer to NULL until - * we have drained - to drain the outgoing packets, we need to - * allow incoming packets. - */ - spin_lock_irqsave(&device->channel->inbound_lock, flags); - device->ext = NULL; - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - - /* Close the channel */ - vmbus_close(device->channel); - - kfree(stor_device); - return 0; -} - -int storvsc_do_io(struct hv_device *device, - struct hv_storvsc_request *request) -{ - struct storvsc_device *stor_device; - struct vstor_packet *vstor_packet; - int ret = 0; - - vstor_packet = &request->vstor_packet; - stor_device = get_out_stor_device(device); - - if (!stor_device) - return -ENODEV; - - - request->device = device; - - - vstor_packet->flags |= REQUEST_COMPLETION_FLAG; - - vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); - - - vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE; - - - vstor_packet->vm_srb.data_transfer_length = - request->data_buffer.len; - - vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; - - if (request->data_buffer.len) { - ret = vmbus_sendpacket_multipagebuffer(device->channel, - &request->data_buffer, - vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request); - } else { - ret = vmbus_sendpacket(device->channel, vstor_packet, - sizeof(struct vstor_packet), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - } - - if (ret != 0) - return ret; - - atomic_inc(&stor_device->num_outstanding_req); - - return ret; -} - -/* - * The channel properties uniquely specify how the device is to be - * presented to the guest. Map this information for use by the block - * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest - * (storvsc_drv) and so scsi devices in the guest are handled by - * native upper level Linux drivers. Consequently, Hyper-V - * block driver, while being a generic block driver, presently does not - * deal with anything other than devices that would need to be presented - * to the guest as an IDE disk. - * - * This function maps the channel properties as embedded in the input - * parameter device_info onto information necessary to register the - * corresponding block device. - * - * Currently, there is no way to stop the emulation of the block device - * on the host side. And so, to prevent the native IDE drivers in Linux - * from taking over these devices (to be managedby Hyper-V block - * driver), we will take over if need be the major of the IDE controllers. - * - */ - -int storvsc_get_major_info(struct storvsc_device_info *device_info, - struct storvsc_major_info *major_info) -{ - static bool ide0_registered; - static bool ide1_registered; - - /* - * For now we only support IDE disks. - */ - major_info->devname = "ide"; - major_info->diskname = "hd"; - - if (device_info->path_id) { - major_info->major = 22; - if (!ide1_registered) { - major_info->do_register = true; - ide1_registered = true; - } else - major_info->do_register = false; - - if (device_info->target_id) - major_info->index = 3; - else - major_info->index = 2; - - return 0; - } else { - major_info->major = 3; - if (!ide0_registered) { - major_info->do_register = true; - ide0_registered = true; - } else - major_info->do_register = false; - - if (device_info->target_id) - major_info->index = 1; - else - major_info->index = 0; - - return 0; - } - - return -ENODEV; -} diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 3e00e70..ddb31cf 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -36,6 +36,535 @@ #include "hyperv.h" #include "hyperv_storage.h" + +/* + * Copyright (c) 2009, Microsoft Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Authors: + * Haiyang Zhang + * Hank Janssen + * K. Y. Srinivasan + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "hyperv.h" +#include "hyperv_storage.h" + + +static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) +{ + struct storvsc_device *stor_device; + + stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); + if (!stor_device) + return NULL; + + stor_device->destroy = false; + init_waitqueue_head(&stor_device->waiting_to_drain); + stor_device->device = device; + device->ext = stor_device; + + return stor_device; +} + + +static inline struct storvsc_device *get_in_stor_device( + struct hv_device *device) +{ + struct storvsc_device *stor_device; + unsigned long flags; + + spin_lock_irqsave(&device->channel->inbound_lock, flags); + stor_device = (struct storvsc_device *)device->ext; + + if (!stor_device) + goto get_in_err; + + /* + * If the device is being destroyed; allow incoming + * traffic only to cleanup outstanding requests. + */ + + if (stor_device->destroy && + (atomic_read(&stor_device->num_outstanding_req) == 0)) + stor_device = NULL; + +get_in_err: + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + return stor_device; + +} + +static int storvsc_channel_init(struct hv_device *device) +{ + struct storvsc_device *stor_device; + struct hv_storvsc_request *request; + struct vstor_packet *vstor_packet; + int ret, t; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return -ENODEV; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + /* + * Now, initiate the vsc/vsp initialization protocol on the open + * channel + */ + memset(request, 0, sizeof(struct hv_storvsc_request)); + init_completion(&request->wait_event); + vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + + ret = vmbus_sendpacket(device->channel, vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret != 0) + goto cleanup; + + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + goto cleanup; + + + /* reuse the packet for version range supported */ + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + + vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT; + FILL_VMSTOR_REVISION(vstor_packet->version.revision); + + ret = vmbus_sendpacket(device->channel, vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret != 0) + goto cleanup; + + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + goto cleanup; + + + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + vstor_packet->storage_channel_properties.port_number = + stor_device->port_number; + + ret = vmbus_sendpacket(device->channel, vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + + if (ret != 0) + goto cleanup; + + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + goto cleanup; + + stor_device->path_id = vstor_packet->storage_channel_properties.path_id; + stor_device->target_id + = vstor_packet->storage_channel_properties.target_id; + + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + + ret = vmbus_sendpacket(device->channel, vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + + if (ret != 0) + goto cleanup; + + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + goto cleanup; + + +cleanup: + return ret; +} + +static void storvsc_on_io_completion(struct hv_device *device, + struct vstor_packet *vstor_packet, + struct hv_storvsc_request *request) +{ + struct storvsc_device *stor_device; + struct vstor_packet *stor_pkt; + + stor_device = (struct storvsc_device *)device->ext; + + stor_pkt = &request->vstor_packet; + + + /* Copy over the status...etc */ + stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; + stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; + stor_pkt->vm_srb.sense_info_length = + vstor_packet->vm_srb.sense_info_length; + + if (vstor_packet->vm_srb.scsi_status != 0 || + vstor_packet->vm_srb.srb_status != 1){ + DPRINT_WARN(STORVSC, + "cmd 0x%x scsi status 0x%x srb status 0x%x\n", + stor_pkt->vm_srb.cdb[0], + vstor_packet->vm_srb.scsi_status, + vstor_packet->vm_srb.srb_status); + } + + if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { + /* CHECK_CONDITION */ + if (vstor_packet->vm_srb.srb_status & 0x80) { + /* autosense data available */ + DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data " + "valid - len %d\n", request, + vstor_packet->vm_srb.sense_info_length); + + memcpy(request->sense_buffer, + vstor_packet->vm_srb.sense_data, + vstor_packet->vm_srb.sense_info_length); + + } + } + + stor_pkt->vm_srb.data_transfer_length = + vstor_packet->vm_srb.data_transfer_length; + + request->on_io_completion(request); + + if (atomic_dec_and_test(&stor_device->num_outstanding_req) && + stor_device->drain_notify) + wake_up(&stor_device->waiting_to_drain); + + +} + +static void storvsc_on_receive(struct hv_device *device, + struct vstor_packet *vstor_packet, + struct hv_storvsc_request *request) +{ + switch (vstor_packet->operation) { + case VSTOR_OPERATION_COMPLETE_IO: + storvsc_on_io_completion(device, vstor_packet, request); + break; + case VSTOR_OPERATION_REMOVE_DEVICE: + + default: + break; + } +} + +static void storvsc_on_channel_callback(void *context) +{ + struct hv_device *device = (struct hv_device *)context; + struct storvsc_device *stor_device; + u32 bytes_recvd; + u64 request_id; + unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)]; + struct hv_storvsc_request *request; + int ret; + + + stor_device = get_in_stor_device(device); + if (!stor_device) + return; + + do { + ret = vmbus_recvpacket(device->channel, packet, + ALIGN(sizeof(struct vstor_packet), 8), + &bytes_recvd, &request_id); + if (ret == 0 && bytes_recvd > 0) { + + request = (struct hv_storvsc_request *) + (unsigned long)request_id; + + if ((request == &stor_device->init_request) || + (request == &stor_device->reset_request)) { + + memcpy(&request->vstor_packet, packet, + sizeof(struct vstor_packet)); + complete(&request->wait_event); + } else { + storvsc_on_receive(device, + (struct vstor_packet *)packet, + request); + } + } else { + break; + } + } while (1); + + return; +} + +static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) +{ + struct vmstorage_channel_properties props; + int ret; + + memset(&props, 0, sizeof(struct vmstorage_channel_properties)); + + /* Open the channel */ + ret = vmbus_open(device->channel, + ring_size, + ring_size, + (void *)&props, + sizeof(struct vmstorage_channel_properties), + storvsc_on_channel_callback, device); + + if (ret != 0) + return ret; + + ret = storvsc_channel_init(device); + + return ret; +} + +int storvsc_dev_add(struct hv_device *device, + void *additional_info) +{ + struct storvsc_device *stor_device; + struct storvsc_device_info *device_info; + int ret = 0; + + device_info = (struct storvsc_device_info *)additional_info; + stor_device = alloc_stor_device(device); + if (!stor_device) + return -ENOMEM; + + /* Save the channel properties to our storvsc channel */ + + /* + * If we support more than 1 scsi channel, we need to set the + * port number here to the scsi channel but how do we get the + * scsi channel prior to the bus scan. + * + * The host does not support this. + */ + + stor_device->port_number = device_info->port_number; + /* Send it back up */ + ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size); + if (ret) { + kfree(stor_device); + return ret; + } + device_info->path_id = stor_device->path_id; + device_info->target_id = stor_device->target_id; + + return ret; +} + +int storvsc_dev_remove(struct hv_device *device) +{ + struct storvsc_device *stor_device; + unsigned long flags; + + stor_device = (struct storvsc_device *)device->ext; + + spin_lock_irqsave(&device->channel->inbound_lock, flags); + stor_device->destroy = true; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + + /* + * At this point, all outbound traffic should be disable. We + * only allow inbound traffic (responses) to proceed so that + * outstanding requests can be completed. + */ + + storvsc_wait_to_drain(stor_device); + + /* + * Since we have already drained, we don't need to busy wait + * as was done in final_release_stor_device() + * Note that we cannot set the ext pointer to NULL until + * we have drained - to drain the outgoing packets, we need to + * allow incoming packets. + */ + spin_lock_irqsave(&device->channel->inbound_lock, flags); + device->ext = NULL; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + + /* Close the channel */ + vmbus_close(device->channel); + + kfree(stor_device); + return 0; +} + +int storvsc_do_io(struct hv_device *device, + struct hv_storvsc_request *request) +{ + struct storvsc_device *stor_device; + struct vstor_packet *vstor_packet; + int ret = 0; + + vstor_packet = &request->vstor_packet; + stor_device = get_out_stor_device(device); + + if (!stor_device) + return -ENODEV; + + + request->device = device; + + + vstor_packet->flags |= REQUEST_COMPLETION_FLAG; + + vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); + + + vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE; + + + vstor_packet->vm_srb.data_transfer_length = + request->data_buffer.len; + + vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; + + if (request->data_buffer.len) { + ret = vmbus_sendpacket_multipagebuffer(device->channel, + &request->data_buffer, + vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request); + } else { + ret = vmbus_sendpacket(device->channel, vstor_packet, + sizeof(struct vstor_packet), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + } + + if (ret != 0) + return ret; + + atomic_inc(&stor_device->num_outstanding_req); + + return ret; +} + +/* + * The channel properties uniquely specify how the device is to be + * presented to the guest. Map this information for use by the block + * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest + * (storvsc_drv) and so scsi devices in the guest are handled by + * native upper level Linux drivers. Consequently, Hyper-V + * block driver, while being a generic block driver, presently does not + * deal with anything other than devices that would need to be presented + * to the guest as an IDE disk. + * + * This function maps the channel properties as embedded in the input + * parameter device_info onto information necessary to register the + * corresponding block device. + * + * Currently, there is no way to stop the emulation of the block device + * on the host side. And so, to prevent the native IDE drivers in Linux + * from taking over these devices (to be managedby Hyper-V block + * driver), we will take over if need be the major of the IDE controllers. + * + */ + +int storvsc_get_major_info(struct storvsc_device_info *device_info, + struct storvsc_major_info *major_info) +{ + static bool ide0_registered; + static bool ide1_registered; + + /* + * For now we only support IDE disks. + */ + major_info->devname = "ide"; + major_info->diskname = "hd"; + + if (device_info->path_id) { + major_info->major = 22; + if (!ide1_registered) { + major_info->do_register = true; + ide1_registered = true; + } else + major_info->do_register = false; + + if (device_info->target_id) + major_info->index = 3; + else + major_info->index = 2; + + return 0; + } else { + major_info->major = 3; + if (!ide0_registered) { + major_info->do_register = true; + ide0_registered = true; + } else + major_info->do_register = false; + + if (device_info->target_id) + major_info->index = 1; + else + major_info->index = 0; + + return 0; + } + + return -ENODEV; +} static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; module_param(storvsc_ringbuffer_size, int, S_IRUGO); -- cgit v1.1 From a1be1706ed0c6d8b93a1aa8fdb03810508fdae3e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:23 -0700 Subject: Staging: hv: storvsc: Cleanup storvsc_drv.c after adding the contents of storvsc.c Cleanup storvsc_drv.c after adding the contents of storvsc.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 147 +++++++-------------------------------- 1 file changed, 27 insertions(+), 120 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ddb31cf..096f615 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -19,11 +19,17 @@ * Hank Janssen * K. Y. Srinivasan */ + +#include +#include +#include +#include +#include +#include #include #include #include #include -#include #include #include #include @@ -37,39 +43,28 @@ #include "hyperv_storage.h" -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ -#include -#include -#include -#include -#include -#include -#include +static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; -#include "hyperv.h" -#include "hyperv_storage.h" +module_param(storvsc_ringbuffer_size, int, S_IRUGO); +MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); + +struct hv_host_device { + struct hv_device *dev; + struct kmem_cache *request_pool; + unsigned int port; + unsigned char path; + unsigned char target; +}; + +struct storvsc_cmd_request { + struct list_head entry; + struct scsi_cmnd *cmd; + unsigned int bounce_sgl_count; + struct scatterlist *bounce_sgl; + + struct hv_storvsc_request request; +}; static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) { @@ -500,94 +495,6 @@ int storvsc_do_io(struct hv_device *device, return ret; } -/* - * The channel properties uniquely specify how the device is to be - * presented to the guest. Map this information for use by the block - * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest - * (storvsc_drv) and so scsi devices in the guest are handled by - * native upper level Linux drivers. Consequently, Hyper-V - * block driver, while being a generic block driver, presently does not - * deal with anything other than devices that would need to be presented - * to the guest as an IDE disk. - * - * This function maps the channel properties as embedded in the input - * parameter device_info onto information necessary to register the - * corresponding block device. - * - * Currently, there is no way to stop the emulation of the block device - * on the host side. And so, to prevent the native IDE drivers in Linux - * from taking over these devices (to be managedby Hyper-V block - * driver), we will take over if need be the major of the IDE controllers. - * - */ - -int storvsc_get_major_info(struct storvsc_device_info *device_info, - struct storvsc_major_info *major_info) -{ - static bool ide0_registered; - static bool ide1_registered; - - /* - * For now we only support IDE disks. - */ - major_info->devname = "ide"; - major_info->diskname = "hd"; - - if (device_info->path_id) { - major_info->major = 22; - if (!ide1_registered) { - major_info->do_register = true; - ide1_registered = true; - } else - major_info->do_register = false; - - if (device_info->target_id) - major_info->index = 3; - else - major_info->index = 2; - - return 0; - } else { - major_info->major = 3; - if (!ide0_registered) { - major_info->do_register = true; - ide0_registered = true; - } else - major_info->do_register = false; - - if (device_info->target_id) - major_info->index = 1; - else - major_info->index = 0; - - return 0; - } - - return -ENODEV; -} -static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; - -module_param(storvsc_ringbuffer_size, int, S_IRUGO); -MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); - -struct hv_host_device { - struct hv_device *dev; - struct kmem_cache *request_pool; - unsigned int port; - unsigned char path; - unsigned char target; -}; - -struct storvsc_cmd_request { - struct list_head entry; - struct scsi_cmnd *cmd; - - unsigned int bounce_sgl_count; - struct scatterlist *bounce_sgl; - - struct hv_storvsc_request request; -}; - static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path) { *target = -- cgit v1.1 From f0d79fe9c564fbe1e09d8366d0863611bc57cafa Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:24 -0700 Subject: Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c As part of further cleanup of storvsc, add the contents of hyperv_storage.h to storvsc_drv.c and do the necessary adjustments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_storage.h | 322 ------------------------------------ drivers/staging/hv/storvsc_drv.c | 277 ++++++++++++++++++++++++++++++- 2 files changed, 276 insertions(+), 323 deletions(-) delete mode 100644 drivers/staging/hv/hyperv_storage.h (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h deleted file mode 100644 index 687cdc5..0000000 --- a/drivers/staging/hv/hyperv_storage.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * - * Copyright (c) 2011, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ - -#ifndef _HYPERV_STORAGE_H -#define _HYPERV_STORAGE_H - - -/* vstorage.w revision number. This is used in the case of a version match, */ -/* to alert the user that structure sizes may be mismatched even though the */ -/* protocol versions match. */ - - -#define REVISION_STRING(REVISION_) #REVISION_ -#define FILL_VMSTOR_REVISION(RESULT_LVALUE_) \ - do { \ - char *revision_string \ - = REVISION_STRING($Rev : 6 $) + 6; \ - RESULT_LVALUE_ = 0; \ - while (*revision_string >= '0' \ - && *revision_string <= '9') { \ - RESULT_LVALUE_ *= 10; \ - RESULT_LVALUE_ += *revision_string - '0'; \ - revision_string++; \ - } \ - } while (0) - -/* Major/minor macros. Minor version is in LSB, meaning that earlier flat */ -/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */ -#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff) -#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) -#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ - (((MINOR_) & 0xff))) -#define VMSTOR_INVALID_PROTOCOL_VERSION (-1) - -/* Version history: */ -/* V1 Beta 0.1 */ -/* V1 RC < 2008/1/31 1.0 */ -/* V1 RC > 2008/1/31 2.0 */ -#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0) - - - - -/* This will get replaced with the max transfer length that is possible on */ -/* the host adapter. */ -/* The max transfer length will be published when we offer a vmbus channel. */ -#define MAX_TRANSFER_LENGTH 0x40000 -#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \ - sizeof(struct vstor_packet) + \ - sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE))) - - -/* Packet structure describing virtual storage requests. */ -enum vstor_packet_operation { - VSTOR_OPERATION_COMPLETE_IO = 1, - VSTOR_OPERATION_REMOVE_DEVICE = 2, - VSTOR_OPERATION_EXECUTE_SRB = 3, - VSTOR_OPERATION_RESET_LUN = 4, - VSTOR_OPERATION_RESET_ADAPTER = 5, - VSTOR_OPERATION_RESET_BUS = 6, - VSTOR_OPERATION_BEGIN_INITIALIZATION = 7, - VSTOR_OPERATION_END_INITIALIZATION = 8, - VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, - VSTOR_OPERATION_QUERY_PROPERTIES = 10, - VSTOR_OPERATION_MAXIMUM = 10 -}; - -/* - * Platform neutral description of a scsi request - - * this remains the same across the write regardless of 32/64 bit - * note: it's patterned off the SCSI_PASS_THROUGH structure - */ -#define CDB16GENERIC_LENGTH 0x10 - -#ifndef SENSE_BUFFER_SIZE -#define SENSE_BUFFER_SIZE 0x12 -#endif - -#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14 - -struct vmscsi_request { - unsigned short length; - unsigned char srb_status; - unsigned char scsi_status; - - unsigned char port_number; - unsigned char path_id; - unsigned char target_id; - unsigned char lun; - - unsigned char cdb_length; - unsigned char sense_info_length; - unsigned char data_in; - unsigned char reserved; - - unsigned int data_transfer_length; - - union { - unsigned char cdb[CDB16GENERIC_LENGTH]; - unsigned char sense_data[SENSE_BUFFER_SIZE]; - unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; - }; -} __attribute((packed)); - - -/* - * This structure is sent during the intialization phase to get the different - * properties of the channel. - */ -struct vmstorage_channel_properties { - unsigned short protocol_version; - unsigned char path_id; - unsigned char target_id; - - /* Note: port number is only really known on the client side */ - unsigned int port_number; - unsigned int flags; - unsigned int max_transfer_bytes; - - /* This id is unique for each channel and will correspond with */ - /* vendor specific data in the inquirydata */ - unsigned long long unique_id; -} __packed; - -/* This structure is sent during the storage protocol negotiations. */ -struct vmstorage_protocol_version { - /* Major (MSW) and minor (LSW) version numbers. */ - unsigned short major_minor; - - /* - * Revision number is auto-incremented whenever this file is changed - * (See FILL_VMSTOR_REVISION macro above). Mismatch does not - * definitely indicate incompatibility--but it does indicate mismatched - * builds. - */ - unsigned short revision; -} __packed; - -/* Channel Property Flags */ -#define STORAGE_CHANNEL_REMOVABLE_FLAG 0x1 -#define STORAGE_CHANNEL_EMULATED_IDE_FLAG 0x2 - -struct vstor_packet { - /* Requested operation type */ - enum vstor_packet_operation operation; - - /* Flags - see below for values */ - unsigned int flags; - - /* Status of the request returned from the server side. */ - unsigned int status; - - /* Data payload area */ - union { - /* - * Structure used to forward SCSI commands from the - * client to the server. - */ - struct vmscsi_request vm_srb; - - /* Structure used to query channel properties. */ - struct vmstorage_channel_properties storage_channel_properties; - - /* Used during version negotiations. */ - struct vmstorage_protocol_version version; - }; -} __packed; - -/* Packet flags */ -/* - * This flag indicates that the server should send back a completion for this - * packet. - */ -#define REQUEST_COMPLETION_FLAG 0x1 - -/* This is the set of flags that the vsc can set in any packets it sends */ -#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG) - - -#include -#include -#include "hyperv_storage.h" -#include "hyperv.h" - -/* Defines */ -#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -#define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) - -#define STORVSC_MAX_IO_REQUESTS 128 - -/* - * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In - * reality, the path/target is not used (ie always set to 0) so our - * scsi host adapter essentially has 1 bus with 1 target that contains - * up to 256 luns. - */ -#define STORVSC_MAX_LUNS_PER_TARGET 64 -#define STORVSC_MAX_TARGETS 1 -#define STORVSC_MAX_CHANNELS 1 - -struct hv_storvsc_request; - -/* Matches Windows-end */ -enum storvsc_request_type { - WRITE_TYPE, - READ_TYPE, - UNKNOWN_TYPE, -}; - - -struct hv_storvsc_request { - struct hv_storvsc_request *request; - struct hv_device *device; - - /* Synchronize the request/response if needed */ - struct completion wait_event; - - unsigned char *sense_buffer; - void *context; - void (*on_io_completion)(struct hv_storvsc_request *request); - struct hv_multipage_buffer data_buffer; - - struct vstor_packet vstor_packet; -}; - - -struct storvsc_device_info { - u32 ring_buffer_size; - unsigned int port_number; - unsigned char path_id; - unsigned char target_id; -}; - -struct storvsc_major_info { - int major; - int index; - bool do_register; - char *devname; - char *diskname; -}; - -/* A storvsc device is a device object that contains a vmbus channel */ -struct storvsc_device { - struct hv_device *device; - - bool destroy; - bool drain_notify; - atomic_t num_outstanding_req; - - wait_queue_head_t waiting_to_drain; - - /* - * Each unique Port/Path/Target represents 1 channel ie scsi - * controller. In reality, the pathid, targetid is always 0 - * and the port is set by us - */ - unsigned int port_number; - unsigned char path_id; - unsigned char target_id; - - /* Used for vsc/vsp channel reset process */ - struct hv_storvsc_request init_request; - struct hv_storvsc_request reset_request; -}; - - -static inline struct storvsc_device *get_out_stor_device( - struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = (struct storvsc_device *)device->ext; - - if (stor_device && stor_device->destroy) - stor_device = NULL; - - return stor_device; -} - - -static inline void storvsc_wait_to_drain(struct storvsc_device *dev) -{ - dev->drain_notify = true; - wait_event(dev->waiting_to_drain, - atomic_read(&dev->num_outstanding_req) == 0); - dev->drain_notify = false; -} - -/* Interface */ - -int storvsc_dev_add(struct hv_device *device, - void *additional_info); -int storvsc_dev_remove(struct hv_device *device); - -int storvsc_do_io(struct hv_device *device, - struct hv_storvsc_request *request); - -int storvsc_get_major_info(struct storvsc_device_info *device_info, - struct storvsc_major_info *major_info); - -#endif /* _HYPERV_STORAGE_H */ diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 096f615..4a95f8b 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -40,7 +41,281 @@ #include #include "hyperv.h" -#include "hyperv_storage.h" + +/* to alert the user that structure sizes may be mismatched even though the */ +/* protocol versions match. */ + + +#define REVISION_STRING(REVISION_) #REVISION_ +#define FILL_VMSTOR_REVISION(RESULT_LVALUE_) \ + do { \ + char *revision_string \ + = REVISION_STRING($Rev : 6 $) + 6; \ + RESULT_LVALUE_ = 0; \ + while (*revision_string >= '0' \ + && *revision_string <= '9') { \ + RESULT_LVALUE_ *= 10; \ + RESULT_LVALUE_ += *revision_string - '0'; \ + revision_string++; \ + } \ + } while (0) + +/* Major/minor macros. Minor version is in LSB, meaning that earlier flat */ +/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */ +#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff) +#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) +#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff))) +#define VMSTOR_INVALID_PROTOCOL_VERSION (-1) + +/* Version history: */ +/* V1 Beta 0.1 */ +/* V1 RC < 2008/1/31 1.0 */ +/* V1 RC > 2008/1/31 2.0 */ +#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0) + + + + +/* This will get replaced with the max transfer length that is possible on */ +/* the host adapter. */ +/* The max transfer length will be published when we offer a vmbus channel. */ +#define MAX_TRANSFER_LENGTH 0x40000 +#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \ + sizeof(struct vstor_packet) + \ + sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE))) + + +/* Packet structure describing virtual storage requests. */ +enum vstor_packet_operation { + VSTOR_OPERATION_COMPLETE_IO = 1, + VSTOR_OPERATION_REMOVE_DEVICE = 2, + VSTOR_OPERATION_EXECUTE_SRB = 3, + VSTOR_OPERATION_RESET_LUN = 4, + VSTOR_OPERATION_RESET_ADAPTER = 5, + VSTOR_OPERATION_RESET_BUS = 6, + VSTOR_OPERATION_BEGIN_INITIALIZATION = 7, + VSTOR_OPERATION_END_INITIALIZATION = 8, + VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, + VSTOR_OPERATION_QUERY_PROPERTIES = 10, + VSTOR_OPERATION_MAXIMUM = 10 +}; + +/* + * Platform neutral description of a scsi request - + * this remains the same across the write regardless of 32/64 bit + * note: it's patterned off the SCSI_PASS_THROUGH structure + */ +#define CDB16GENERIC_LENGTH 0x10 + +#ifndef SENSE_BUFFER_SIZE +#define SENSE_BUFFER_SIZE 0x12 +#endif + +#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14 + +struct vmscsi_request { + unsigned short length; + unsigned char srb_status; + unsigned char scsi_status; + + unsigned char port_number; + unsigned char path_id; + unsigned char target_id; + unsigned char lun; + + unsigned char cdb_length; + unsigned char sense_info_length; + unsigned char data_in; + unsigned char reserved; + + unsigned int data_transfer_length; + + union { + unsigned char cdb[CDB16GENERIC_LENGTH]; + unsigned char sense_data[SENSE_BUFFER_SIZE]; + unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; + }; +} __attribute((packed)); + + +/* + * This structure is sent during the intialization phase to get the different + * properties of the channel. + */ +struct vmstorage_channel_properties { + unsigned short protocol_version; + unsigned char path_id; + unsigned char target_id; + + /* Note: port number is only really known on the client side */ + unsigned int port_number; + unsigned int flags; + unsigned int max_transfer_bytes; + + /* This id is unique for each channel and will correspond with */ + /* vendor specific data in the inquirydata */ + unsigned long long unique_id; +} __packed; + +/* This structure is sent during the storage protocol negotiations. */ +struct vmstorage_protocol_version { + /* Major (MSW) and minor (LSW) version numbers. */ + unsigned short major_minor; + + /* + * Revision number is auto-incremented whenever this file is changed + * (See FILL_VMSTOR_REVISION macro above). Mismatch does not + * definitely indicate incompatibility--but it does indicate mismatched + * builds. + */ + unsigned short revision; +} __packed; + +/* Channel Property Flags */ +#define STORAGE_CHANNEL_REMOVABLE_FLAG 0x1 +#define STORAGE_CHANNEL_EMULATED_IDE_FLAG 0x2 + +struct vstor_packet { + /* Requested operation type */ + enum vstor_packet_operation operation; + + /* Flags - see below for values */ + unsigned int flags; + + /* Status of the request returned from the server side. */ + unsigned int status; + + /* Data payload area */ + union { + /* + * Structure used to forward SCSI commands from the + * client to the server. + */ + struct vmscsi_request vm_srb; + + /* Structure used to query channel properties. */ + struct vmstorage_channel_properties storage_channel_properties; + + /* Used during version negotiations. */ + struct vmstorage_protocol_version version; + }; +} __packed; + +/* Packet flags */ +/* + * This flag indicates that the server should send back a completion for this + * packet. + */ +#define REQUEST_COMPLETION_FLAG 0x1 + +/* This is the set of flags that the vsc can set in any packets it sends */ +#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG) + + +/* Defines */ +#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) +#define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) + +#define STORVSC_MAX_IO_REQUESTS 128 + +/* + * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In + * reality, the path/target is not used (ie always set to 0) so our + * scsi host adapter essentially has 1 bus with 1 target that contains + * up to 256 luns. + */ +#define STORVSC_MAX_LUNS_PER_TARGET 64 +#define STORVSC_MAX_TARGETS 1 +#define STORVSC_MAX_CHANNELS 1 + +struct hv_storvsc_request; + +/* Matches Windows-end */ +enum storvsc_request_type { + WRITE_TYPE, + READ_TYPE, + UNKNOWN_TYPE, +}; + + +struct hv_storvsc_request { + struct hv_storvsc_request *request; + struct hv_device *device; + + /* Synchronize the request/response if needed */ + struct completion wait_event; + + unsigned char *sense_buffer; + void *context; + void (*on_io_completion)(struct hv_storvsc_request *request); + struct hv_multipage_buffer data_buffer; + + struct vstor_packet vstor_packet; +}; + + +struct storvsc_device_info { + u32 ring_buffer_size; + unsigned int port_number; + unsigned char path_id; + unsigned char target_id; +}; + +struct storvsc_major_info { + int major; + int index; + bool do_register; + char *devname; + char *diskname; +}; + +/* A storvsc device is a device object that contains a vmbus channel */ +struct storvsc_device { + struct hv_device *device; + + bool destroy; + bool drain_notify; + atomic_t num_outstanding_req; + + wait_queue_head_t waiting_to_drain; + + /* + * Each unique Port/Path/Target represents 1 channel ie scsi + * controller. In reality, the pathid, targetid is always 0 + * and the port is set by us + */ + unsigned int port_number; + unsigned char path_id; + unsigned char target_id; + + /* Used for vsc/vsp channel reset process */ + struct hv_storvsc_request init_request; + struct hv_storvsc_request reset_request; +}; + + +static inline struct storvsc_device *get_out_stor_device( + struct hv_device *device) +{ + struct storvsc_device *stor_device; + + stor_device = (struct storvsc_device *)device->ext; + + if (stor_device && stor_device->destroy) + stor_device = NULL; + + return stor_device; +} + + +static inline void storvsc_wait_to_drain(struct storvsc_device *dev) +{ + dev->drain_notify = true; + wait_event(dev->waiting_to_drain, + atomic_read(&dev->num_outstanding_req) == 0); + dev->drain_notify = false; +} static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; -- cgit v1.1 From c1b3d067e419dee621ddd5e8f5d812973a6d0946 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:25 -0700 Subject: Staging: hv: storvsc: Cleanup storvsc_drv.c after adding the contents of hyperv_storage.h Cleanup storvsc_drv.c after adding the contents of hyperv_storage.h. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 62 +++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 36 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 4a95f8b..0bb4e0e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -42,6 +42,12 @@ #include "hyperv.h" +#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) +static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; + +module_param(storvsc_ringbuffer_size, int, S_IRUGO); +MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); + /* to alert the user that structure sizes may be mismatched even though the */ /* protocol versions match. */ @@ -214,8 +220,6 @@ struct vstor_packet { /* Defines */ -#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -#define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) #define STORVSC_MAX_IO_REQUESTS 128 @@ -262,13 +266,6 @@ struct storvsc_device_info { unsigned char target_id; }; -struct storvsc_major_info { - int major; - int index; - bool do_register; - char *devname; - char *diskname; -}; /* A storvsc device is a device object that contains a vmbus channel */ struct storvsc_device { @@ -294,6 +291,23 @@ struct storvsc_device { struct hv_storvsc_request reset_request; }; +struct hv_host_device { + struct hv_device *dev; + struct kmem_cache *request_pool; + unsigned int port; + unsigned char path; + unsigned char target; +}; + +struct storvsc_cmd_request { + struct list_head entry; + struct scsi_cmnd *cmd; + + unsigned int bounce_sgl_count; + struct scatterlist *bounce_sgl; + + struct hv_storvsc_request request; +}; static inline struct storvsc_device *get_out_stor_device( struct hv_device *device) @@ -317,30 +331,6 @@ static inline void storvsc_wait_to_drain(struct storvsc_device *dev) dev->drain_notify = false; } - -static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; - -module_param(storvsc_ringbuffer_size, int, S_IRUGO); -MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); - -struct hv_host_device { - struct hv_device *dev; - struct kmem_cache *request_pool; - unsigned int port; - unsigned char path; - unsigned char target; -}; - -struct storvsc_cmd_request { - struct list_head entry; - struct scsi_cmnd *cmd; - - unsigned int bounce_sgl_count; - struct scatterlist *bounce_sgl; - - struct hv_storvsc_request request; -}; - static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) { struct storvsc_device *stor_device; @@ -646,7 +636,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) return ret; } -int storvsc_dev_add(struct hv_device *device, +static int storvsc_dev_add(struct hv_device *device, void *additional_info) { struct storvsc_device *stor_device; @@ -681,7 +671,7 @@ int storvsc_dev_add(struct hv_device *device, return ret; } -int storvsc_dev_remove(struct hv_device *device) +static int storvsc_dev_remove(struct hv_device *device) { struct storvsc_device *stor_device; unsigned long flags; @@ -718,7 +708,7 @@ int storvsc_dev_remove(struct hv_device *device) return 0; } -int storvsc_do_io(struct hv_device *device, +static int storvsc_do_io(struct hv_device *device, struct hv_storvsc_request *request) { struct storvsc_device *stor_device; -- cgit v1.1 From 4ed51a21c0f69e1379cf858fc21a9d9022bfe0e7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:26 -0700 Subject: Staging: hv: storvsc: Fixup srb and scsi status for INQUIRY and MODE_SENSE The current VHD handler on the Windows Host does not correctly handle INQUIRY and MODE_SENSE commands with some options. Fixup srb_status in these cases since the failure is not fatal. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 0bb4e0e..72ca25c 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -512,6 +512,23 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt = &request->vstor_packet; + /* + * The current SCSI handling on the host side does + * not correctly handle: + * INQUIRY command with page code parameter set to 0x80 + * MODE_SENSE command with cmd[2] == 0x1c + * + * Setup srb and scsi status so this won't be fatal. + * We do this so we can distinguish truly fatal failues + * (srb status == 0x4) and off-line the device in that case. + */ + + if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || + (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { + vstor_packet->vm_srb.scsi_status = 0; + vstor_packet->vm_srb.srb_status = 0x1; + } + /* Copy over the status...etc */ stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; -- cgit v1.1 From b8de73df1b5143c3d567e707e4dab0b20c82ab54 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:27 -0700 Subject: Staging: hv: storvsc: Fix a typo Fix a typo in a function name. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 72ca25c..ad0f9d4 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1130,9 +1130,9 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) /* - * storvsc_commmand_completion - Command completion processing + * storvsc_command_completion - Command completion processing */ -static void storvsc_commmand_completion(struct hv_storvsc_request *request) +static void storvsc_command_completion(struct hv_storvsc_request *request) { struct storvsc_cmd_request *cmd_request = (struct storvsc_cmd_request *)request->context; @@ -1240,7 +1240,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, break; } - request->on_io_completion = storvsc_commmand_completion; + request->on_io_completion = storvsc_command_completion; request->context = cmd_request;/* scmnd; */ vm_srb->port_number = host_dev->port; -- cgit v1.1 From 2544b794372b63e46384ac4af91c5630e92cf7f4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:28 -0700 Subject: Staging: hv: storvsc: In case of scsi errors offline the device When we do get fatal errors from the host, offline the device since the host has already tried all possible recovery actions. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ad0f9d4..22a1d75 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1154,7 +1154,15 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) } } - scmnd->result = vm_srb->scsi_status; + /* + * If there is an error; offline the device since all + * error recovery strategies would have already been + * deployed on the host side. + */ + if (vm_srb->srb_status == 0x4) + scmnd->result = DID_TARGET_FAILURE << 16; + else + scmnd->result = vm_srb->scsi_status; if (scmnd->result) { if (scsi_normalize_sense(scmnd->sense_buffer, -- cgit v1.1 From 70691ec666a6c04f6f1438d9a0bf495b24e22610 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:29 -0700 Subject: Staging: hv: storvsc: No need to copy from bounce buffer in case of a failure No need to copy from bounce buffer in case of a failure; cleanup the code accordingly. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 22a1d75..d575bc9 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1315,17 +1315,9 @@ retry_request: if (ret == -EAGAIN) { /* no more space */ - if (cmd_request->bounce_sgl_count) { - /* - * FIXME: We can optimize on writes by just skipping - * this - */ - copy_from_bounce_buffer(scsi_sglist(scmnd), - cmd_request->bounce_sgl, - scsi_sg_count(scmnd)); + if (cmd_request->bounce_sgl_count) destroy_bounce_buffer(cmd_request->bounce_sgl, - cmd_request->bounce_sgl_count); - } + cmd_request->bounce_sgl_count); kmem_cache_free(host_dev->request_pool, cmd_request); -- cgit v1.1 From ae2a0b42bfe6e7eb9251bfb05f7a03008df446a8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:30 -0700 Subject: Staging: hv: util: Forcefully shutdown when shutdown is requested When the host requests a "shutdown", make sure we shutdown! Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index f2f456f..876d44a 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -89,7 +89,7 @@ static void shutdown_onchannelcallback(void *context) } if (execute_shutdown == true) - orderly_poweroff(false); + orderly_poweroff(true); } /* -- cgit v1.1 From 95ff7cde91f5513ebc95ccf0cd482f07dc3454e4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:31 -0700 Subject: Staging: hv: util: Adjust guest time in a process context The current code was adjusting guest time in interrupt context; do this in process context since we may have to initiate cross-processor interrupts as part of setting time. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index 876d44a..e29a2a2 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -107,6 +107,24 @@ static inline void do_adj_guesttime(u64 hosttime) } /* + * Set the host time in a process context. + */ + +struct adj_time_work { + struct work_struct work; + u64 host_time; +}; + +static void hv_set_host_time(struct work_struct *work) +{ + struct adj_time_work *wrk; + + wrk = container_of(work, struct adj_time_work, work); + do_adj_guesttime(wrk->host_time); + kfree(wrk); +} + +/* * Synchronize time with host after reboot, restore, etc. * * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM. @@ -119,17 +137,26 @@ static inline void do_adj_guesttime(u64 hosttime) */ static inline void adj_guesttime(u64 hosttime, u8 flags) { + struct adj_time_work *wrk; static s32 scnt = 50; + wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC); + if (wrk == NULL) + return; + + wrk->host_time = hosttime; if ((flags & ICTIMESYNCFLAG_SYNC) != 0) { - do_adj_guesttime(hosttime); + INIT_WORK(&wrk->work, hv_set_host_time); + schedule_work(&wrk->work); return; } if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) { scnt--; - do_adj_guesttime(hosttime); - } + INIT_WORK(&wrk->work, hv_set_host_time); + schedule_work(&wrk->work); + } else + kfree(wrk); } /* -- cgit v1.1 From 76c39d429d606d8f9b354ee2b1973b76c8331b1f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:32 -0700 Subject: Staging: hv: vmbus: Check before invoking the channel callback When we close a channel, we set the corresponding callback function to NULL. Check before invoking the channel callback. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index a88ad70..7a3ec75 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -222,7 +222,7 @@ static void process_chn_event(u32 relid) */ channel = relid2channel(relid); - if (channel) { + if (channel && (channel->onchannel_callback != NULL)) { channel->onchannel_callback(channel->channel_callback_context); } else { pr_err("channel not found for relid - %u\n", relid); -- cgit v1.1 From dad76bf73fc20b42d020fe5a93dbe4b4868e7681 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:33 -0700 Subject: Staging: hv: vmbus: Properly deal with de-registering channel callback Ensure that we correctly handle racing invocations of the channel callback when the channel is being closed. We do this using the channel's inbound_lock. A side-effect of this strategy is that we avoid repeatedly picking up this lock as we drain the inbound ring-buffer. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel.c | 20 +++++--------------- drivers/staging/hv/connection.c | 3 +++ drivers/staging/hv/netvsc.c | 3 --- drivers/staging/hv/storvsc_drv.c | 3 --- 4 files changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index ac92c1f..b6f3d38 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -513,9 +513,12 @@ void vmbus_close(struct vmbus_channel *channel) { struct vmbus_channel_close_channel *msg; int ret; + unsigned long flags; /* Stop callback and cancel the timer asap */ + spin_lock_irqsave(&channel->inbound_lock, flags); channel->onchannel_callback = NULL; + spin_unlock_irqrestore(&channel->inbound_lock, flags); /* Send a closing message */ @@ -735,19 +738,15 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, u32 packetlen; u32 userlen; int ret; - unsigned long flags; *buffer_actual_len = 0; *requestid = 0; - spin_lock_irqsave(&channel->inbound_lock, flags); ret = hv_ringbuffer_peek(&channel->inbound, &desc, sizeof(struct vmpacket_descriptor)); - if (ret != 0) { - spin_unlock_irqrestore(&channel->inbound_lock, flags); + if (ret != 0) return 0; - } packetlen = desc.len8 << 3; userlen = packetlen - (desc.offset8 << 3); @@ -755,7 +754,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, *buffer_actual_len = userlen; if (userlen > bufferlen) { - spin_unlock_irqrestore(&channel->inbound_lock, flags); pr_err("Buffer too small - got %d needs %d\n", bufferlen, userlen); @@ -768,7 +766,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen, (desc.offset8 << 3)); - spin_unlock_irqrestore(&channel->inbound_lock, flags); return 0; } @@ -785,19 +782,15 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, u32 packetlen; u32 userlen; int ret; - unsigned long flags; *buffer_actual_len = 0; *requestid = 0; - spin_lock_irqsave(&channel->inbound_lock, flags); ret = hv_ringbuffer_peek(&channel->inbound, &desc, sizeof(struct vmpacket_descriptor)); - if (ret != 0) { - spin_unlock_irqrestore(&channel->inbound_lock, flags); + if (ret != 0) return 0; - } packetlen = desc.len8 << 3; @@ -806,8 +799,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, *buffer_actual_len = packetlen; if (packetlen > bufferlen) { - spin_unlock_irqrestore(&channel->inbound_lock, flags); - pr_err("Buffer too small - needed %d bytes but " "got space for only %d bytes\n", packetlen, bufferlen); @@ -819,7 +810,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, /* Copy over the entire packet to the user buffer */ ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0); - spin_unlock_irqrestore(&channel->inbound_lock, flags); return 0; } EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index 7a3ec75..6aab802 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -215,6 +215,7 @@ struct vmbus_channel *relid2channel(u32 relid) static void process_chn_event(u32 relid) { struct vmbus_channel *channel; + unsigned long flags; /* * Find the channel based on this relid and invokes the @@ -222,11 +223,13 @@ static void process_chn_event(u32 relid) */ channel = relid2channel(relid); + spin_lock_irqsave(&channel->inbound_lock, flags); if (channel && (channel->onchannel_callback != NULL)) { channel->onchannel_callback(channel->channel_callback_context); } else { pr_err("channel not found for relid - %u\n", relid); } + spin_unlock_irqrestore(&channel->inbound_lock, flags); } /* diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 9828f0b..e4cc40a 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -62,9 +62,7 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device) static struct netvsc_device *get_inbound_net_device(struct hv_device *device) { struct netvsc_device *net_device; - unsigned long flags; - spin_lock_irqsave(&device->channel->inbound_lock, flags); net_device = device->ext; if (!net_device) @@ -75,7 +73,6 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device) net_device = NULL; get_in_err: - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); return net_device; } diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index d575bc9..3686d10 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -352,9 +352,7 @@ static inline struct storvsc_device *get_in_stor_device( struct hv_device *device) { struct storvsc_device *stor_device; - unsigned long flags; - spin_lock_irqsave(&device->channel->inbound_lock, flags); stor_device = (struct storvsc_device *)device->ext; if (!stor_device) @@ -370,7 +368,6 @@ static inline struct storvsc_device *get_in_stor_device( stor_device = NULL; get_in_err: - spin_unlock_irqrestore(&device->channel->inbound_lock, flags); return stor_device; } -- cgit v1.1 From e61ee14f0e9be1ff3d0d3e6168d47125729864c7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:34 -0700 Subject: Staging: hv: Fix a bug in vmbus_match() The recent checkin that add a private pointer to hv_vmbus_device_id introduced this bug in vmbus_match; fix it. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index be62b62..51002c05 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -273,7 +273,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver) for (; !is_null_guid(id_array->guid); id_array++) if (!memcmp(&id_array->guid, &hv_dev->dev_type.b, - sizeof(struct hv_vmbus_device_id))) + sizeof(uuid_le))) return 1; return 0; -- cgit v1.1 From ae4636e6c0d1d8d326f38586121478d7b32150b7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:35 -0700 Subject: Staging: hv: vmbus: Get rid of vmbus_on_isr() by inlining the code Get rid of vmbus_on_isr() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 51002c05..5dcc8c3 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -437,53 +437,36 @@ static void vmbus_on_msg_dpc(unsigned long data) } } -/* - * vmbus_on_isr - ISR routine - */ -static int vmbus_on_isr(void) +static irqreturn_t vmbus_isr(int irq, void *dev_id) { - int ret = 0; int cpu = smp_processor_id(); void *page_addr; struct hv_message *msg; union hv_synic_event_flags *event; + bool handled = false; page_addr = hv_context.synic_message_page[cpu]; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; /* Check if there are actual msgs to be process */ - if (msg->header.message_type != HVMSG_NONE) - ret |= 0x1; + if (msg->header.message_type != HVMSG_NONE) { + handled = true; + tasklet_schedule(&msg_dpc); + } page_addr = hv_context.synic_event_page[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ - if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) - ret |= 0x2; - - return ret; -} - - -static irqreturn_t vmbus_isr(int irq, void *dev_id) -{ - int ret; - - ret = vmbus_on_isr(); - - /* Schedules a dpc if necessary */ - if (ret > 0) { - if (test_bit(0, (unsigned long *)&ret)) - tasklet_schedule(&msg_dpc); - - if (test_bit(1, (unsigned long *)&ret)) - tasklet_schedule(&event_dpc); + if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { + handled = true; + tasklet_schedule(&event_dpc); + } + if (handled) return IRQ_HANDLED; - } else { + else return IRQ_NONE; - } } /* -- cgit v1.1 From 93511baa06437785758be98ee7a7149c49c8e9c5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:37 -0700 Subject: Staging: hv: vmbus: Do not enable auto eoi Linux interrupt handling code generates the eoi; don't enable auto eoi. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c index 736794e..06f1e15 100644 --- a/drivers/staging/hv/hv.c +++ b/drivers/staging/hv/hv.c @@ -369,7 +369,7 @@ void hv_synic_init(void *irqarg) shared_sint.as_uint64 = 0; shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ shared_sint.masked = false; - shared_sint.auto_eoi = true; + shared_sint.auto_eoi = false; wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); -- cgit v1.1 From 0a4425b65dcdb3dc767c05308dd1078ef86e914c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:38 -0700 Subject: Staging: hv: vmbus: Fixup indentation in vmbus_acpi_add() Fixup indentation in vmbus_acpi_add(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 5dcc8c3..ed18488 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -678,9 +678,8 @@ static int vmbus_acpi_add(struct acpi_device *device) hv_acpi_dev = device; - result = - acpi_walk_resources(device->handle, METHOD_NAME__CRS, - vmbus_walk_resources, &irq); + result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + vmbus_walk_resources, &irq); if (ACPI_FAILURE(result)) { complete(&probe_event); -- cgit v1.1 From 0bce28b62e1927565566f8a1a7f127d196b87039 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:39 -0700 Subject: Staging: hv: vmbus: Get rid of some dated/redundant comments Get rid of some dated/redundant comments in vmbus_drv.c Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index ed18488..757943b 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -391,9 +391,6 @@ static void vmbus_onmessage_work(struct work_struct *work) kfree(ctx); } -/* - * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior - */ static void vmbus_on_msg_dpc(unsigned long data) { int cpu = smp_processor_id(); @@ -490,16 +487,13 @@ static int vmbus_bus_init(int irq) return ret; } - /* Initialize the bus context */ tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0); tasklet_init(&event_dpc, vmbus_on_event, 0); - /* Now, register the bus with LDM */ ret = bus_register(&hv_bus); if (ret) return ret; - /* Get the interrupt resource */ ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, driver_name, hv_acpi_dev); @@ -588,7 +582,6 @@ struct hv_device *vmbus_child_device_create(uuid_le *type, { struct hv_device *child_device_obj; - /* Allocate the new child device */ child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL); if (!child_device_obj) { pr_err("Unable to allocate device object for child device\n"); @@ -613,12 +606,10 @@ int vmbus_child_device_register(struct hv_device *child_device_obj) static atomic_t device_num = ATOMIC_INIT(0); - /* Set the device name. Otherwise, device_register() will fail. */ dev_set_name(&child_device_obj->device, "vmbus_0_%d", atomic_inc_return(&device_num)); - /* The new device belongs to this bus */ - child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */ + child_device_obj->device.bus = &hv_bus; child_device_obj->device.parent = &hv_acpi_dev->dev; child_device_obj->device.release = vmbus_device_release; -- cgit v1.1 From c2ec81cb3e9d6cb6d819155883684d94fab005ad Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:41 -0700 Subject: Staging: hv: vmbus: Get rid of an unnecessary check in vmbus_connect() Get rid of an unnecessary check in vmbus_connect(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index 6aab802..ca92ca3 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -50,10 +50,6 @@ int vmbus_connect(void) struct vmbus_channel_initiate_contact *msg; unsigned long flags; - /* Make sure we are not connecting or connected */ - if (vmbus_connection.conn_state != DISCONNECTED) - return -EISCONN; - /* Initialize the vmbus connection */ vmbus_connection.conn_state = CONNECTING; vmbus_connection.work_queue = create_workqueue("hv_vmbus_con"); -- cgit v1.1 From b737b2e00d99a4c07ba3e50d2f5b154addfe7c76 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:42 -0700 Subject: Staging: hv: vmbus: Fix a checkpatch warning in ring_buffer.c Fix a checkpatch warning in ring_buffer.c Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/ring_buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index 9212699..70e2e66 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -34,7 +34,8 @@ /* Amount of space to write to */ -#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) +#define BYTES_AVAIL_TO_WRITE(r, w, z) \ + ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) /* -- cgit v1.1 From d9add43b485538bd1e6c52d8177231ae31143265 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:43 -0700 Subject: Staging: hv: vmbus: Fix checkpatch warnings in connection.c Fix checkpatch warnings in connection.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index ca92ca3..9e99c04 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -220,11 +220,11 @@ static void process_chn_event(u32 relid) channel = relid2channel(relid); spin_lock_irqsave(&channel->inbound_lock, flags); - if (channel && (channel->onchannel_callback != NULL)) { + if (channel && (channel->onchannel_callback != NULL)) channel->onchannel_callback(channel->channel_callback_context); - } else { + else pr_err("channel not found for relid - %u\n", relid); - } + spin_unlock_irqrestore(&channel->inbound_lock, flags); } @@ -246,16 +246,17 @@ void vmbus_on_event(unsigned long data) if (!recv_int_page[dword]) continue; for (bit = 0; bit < 32; bit++) { - if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) { + if (sync_test_and_clear_bit(bit, + (unsigned long *)&recv_int_page[dword])) { relid = (dword << 5) + bit; - if (relid == 0) { + if (relid == 0) /* * Special case - vmbus * channel protocol msg */ continue; - } + process_chn_event(relid); } } -- cgit v1.1 From bb5da491ffd48f7e401da364d4fb0577ce0e9939 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:44 -0700 Subject: Staging: hv: mousevsc: Fix checkpatch errors and warnings Fix checkpatch errors and warnings. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 090736a..dbb04ee 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -335,7 +335,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL); if (!input_device->hid_desc) { - pr_err("unable to allocate hid descriptor - size %d", desc->bLength); + pr_err("unable to allocate hid descriptor - size %d", + desc->bLength); goto cleanup; } @@ -598,12 +599,12 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) pr_info("synthhid protocol request..."); ret = vmbus_sendpacket(device->channel, request, - sizeof(struct pipe_prt_msg) - - sizeof(unsigned char) + - sizeof(struct synthhid_protocol_request), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + sizeof(struct pipe_prt_msg) - + sizeof(unsigned char) + + sizeof(struct synthhid_protocol_request), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) { pr_err("unable to send synthhid protocol request."); goto cleanup; -- cgit v1.1 From 7f9615e6f6c703c68f84460fe22b858be6c258d1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 27 Aug 2011 14:06:07 +0300 Subject: Staging: hv: netvsc: return negative error codes There was a typo here and we changed the -ENOMEM into +ENOMEM. The error codes aren't used, so this is just a cleanup. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index e4cc40a..30d3139 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -125,7 +125,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) if (ret != 0) { dev_err(&net_device->dev->device, "unable to teardown receive buffer's gpadl"); - return -ret; + return ret; } net_device->recv_buf_gpadl_handle = 0; } -- cgit v1.1 From d531babe8259992be32144f2c80fa5e15f9d4d26 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 31 Aug 2011 14:35:54 -0700 Subject: Staging: hv: util: Deal with driver register failures Properly deal with vmbus_driver_register() failures. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_util.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index e29a2a2..6039217 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -277,6 +277,7 @@ static struct hv_driver util_drv = { static int __init init_hyperv_utils(void) { + int ret; pr_info("Registering HyperV Utility Driver\n"); if (hv_kvp_init()) @@ -289,12 +290,15 @@ static int __init init_hyperv_utils(void) if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) { pr_info("Unable to allocate memory for receive buffer\n"); - kfree(shut_txf_buf); - kfree(time_txf_buf); - kfree(hbeat_txf_buf); - return -ENOMEM; + ret = -ENOMEM; + goto err; } + ret = vmbus_driver_register(&util_drv); + + if (ret != 0) + goto err; + hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback; @@ -303,7 +307,14 @@ static int __init init_hyperv_utils(void) hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; - return vmbus_driver_register(&util_drv); + return 0; + +err: + kfree(shut_txf_buf); + kfree(time_txf_buf); + kfree(hbeat_txf_buf); + + return ret; } static void exit_hyperv_utils(void) -- cgit v1.1 From 8b9987e9050aeba12325a3f0ab0f4a2934c37c3c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 31 Aug 2011 14:35:55 -0700 Subject: Staging: hv: vmbus: Fix a bug in error handling in vmbus_bus_init() Fix a bug in error handling in vmbus_bus_init(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 757943b..b5e06d6 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -492,7 +492,7 @@ static int vmbus_bus_init(int irq) ret = bus_register(&hv_bus); if (ret) - return ret; + goto err_cleanup; ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, driver_name, hv_acpi_dev); @@ -500,10 +500,7 @@ static int vmbus_bus_init(int irq) if (ret != 0) { pr_err("Unable to request IRQ %d\n", irq); - - bus_unregister(&hv_bus); - - return ret; + goto err_unregister; } vector = IRQ0_VECTOR + irq; @@ -514,16 +511,23 @@ static int vmbus_bus_init(int irq) */ on_each_cpu(hv_synic_init, (void *)&vector, 1); ret = vmbus_connect(); - if (ret) { - free_irq(irq, hv_acpi_dev); - bus_unregister(&hv_bus); - return ret; - } - + if (ret) + goto err_irq; vmbus_request_offers(); return 0; + +err_irq: + free_irq(irq, hv_acpi_dev); + +err_unregister: + bus_unregister(&hv_bus); + +err_cleanup: + hv_cleanup(); + + return ret; } /** -- cgit v1.1 From 7341d908af307a34098a9da52f49037d815c868f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 31 Aug 2011 14:35:56 -0700 Subject: Staging: hv: vmbus: Check for events before messages The Windows team has informed us that on Windows guests on Hyper-V, they check for events before messages. They also recommended that we do the same. This patch addresses this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index b5e06d6..cd43ddd 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -442,14 +442,11 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) union hv_synic_event_flags *event; bool handled = false; - page_addr = hv_context.synic_message_page[cpu]; - msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; - - /* Check if there are actual msgs to be process */ - if (msg->header.message_type != HVMSG_NONE) { - handled = true; - tasklet_schedule(&msg_dpc); - } + /* + * Check for events before checking for messages. This is the order + * in which events and messages are checked in Windows guests on + * Hyper-V, and the Windows team suggested we do the same. + */ page_addr = hv_context.synic_event_page[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; @@ -460,6 +457,15 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) tasklet_schedule(&event_dpc); } + page_addr = hv_context.synic_message_page[cpu]; + msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; + + /* Check if there are actual msgs to be processed */ + if (msg->header.message_type != HVMSG_NONE) { + handled = true; + tasklet_schedule(&msg_dpc); + } + if (handled) return IRQ_HANDLED; else -- cgit v1.1 From 24326039b9685e8bfb1532932e18cb458f2a3517 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 31 Aug 2011 14:35:57 -0700 Subject: Staging: hv: vmbus: Cleanup the code in process_chn_event() A channel in Hyper-V is equivalent to a device. Thus, a channel is persistent once it is presented to the guest, even if the driver managing this device is unloaded. By checking and invoking the driver specific callback function under the protection of the channel inbound_lock, we can properly deal with racing driver unloads since an unloading driver sets the callback to NULL under the protection of this inbound_lock. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/connection.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index 9e99c04..649b91b 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -219,11 +219,25 @@ static void process_chn_event(u32 relid) */ channel = relid2channel(relid); + if (!channel) { + pr_err("channel not found for relid - %u\n", relid); + return; + } + + /* + * A channel once created is persistent even when there + * is no driver handling the device. An unloading driver + * sets the onchannel_callback to NULL under the + * protection of the channel inbound_lock. Thus, checking + * and invoking the driver specific callback takes care of + * orderly unloading of the driver. + */ + spin_lock_irqsave(&channel->inbound_lock, flags); - if (channel && (channel->onchannel_callback != NULL)) + if (channel->onchannel_callback != NULL) channel->onchannel_callback(channel->channel_callback_context); else - pr_err("channel not found for relid - %u\n", relid); + pr_err("no channel callback for relid - %u\n", relid); spin_unlock_irqrestore(&channel->inbound_lock, flags); } -- cgit v1.1 From a3e8095886b65af402e24cd5c32173d9acd0123a Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:39 -0700 Subject: staging: hv: remove unnecessary includes in netvsc hyperv.h is included by hyperv_net.h already, so no need to include it again in these C files. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 1 - drivers/staging/hv/netvsc_drv.c | 1 - drivers/staging/hv/rndis_filter.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 30d3139..9a9228c 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -28,7 +28,6 @@ #include #include -#include "hyperv.h" #include "hyperv_net.h" diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 90a3198..30a0cb2 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -38,7 +38,6 @@ #include #include -#include "hyperv.h" #include "hyperv_net.h" struct net_device_context { diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 6db48b9..8416bf2 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -27,7 +27,6 @@ #include #include -#include "hyperv.h" #include "hyperv_net.h" -- cgit v1.1 From c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:40 -0700 Subject: staging: hv: add newline to log messages in netvsc Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 58 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 9a9228c..ef764e6 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -108,7 +108,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) */ if (ret != 0) { dev_err(&net_device->dev->device, "unable to send " - "revoke receive buffer to netvsp"); + "revoke receive buffer to netvsp\n"); return ret; } } @@ -123,7 +123,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) */ if (ret != 0) { dev_err(&net_device->dev->device, - "unable to teardown receive buffer's gpadl"); + "unable to teardown receive buffer's gpadl\n"); return ret; } net_device->recv_buf_gpadl_handle = 0; @@ -155,7 +155,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) net_device = get_outbound_net_device(device); if (!net_device) { dev_err(&device->device, "unable to get net device..." - "device being destroyed?"); + "device being destroyed?\n"); return -ENODEV; } @@ -164,7 +164,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) get_order(net_device->recv_buf_size)); if (!net_device->recv_buf) { dev_err(&device->device, "unable to allocate receive " - "buffer of size %d", net_device->recv_buf_size); + "buffer of size %d\n", net_device->recv_buf_size); ret = -ENOMEM; goto cleanup; } @@ -179,7 +179,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) &net_device->recv_buf_gpadl_handle); if (ret != 0) { dev_err(&device->device, - "unable to establish receive buffer's gpadl"); + "unable to establish receive buffer's gpadl\n"); goto cleanup; } @@ -203,7 +203,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) { dev_err(&device->device, - "unable to send receive buffer's gpadl to netvsp"); + "unable to send receive buffer's gpadl to netvsp\n"); goto cleanup; } @@ -215,7 +215,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) if (init_packet->msg.v1_msg. send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { dev_err(&device->device, "Unable to complete receive buffer " - "initialzation with NetVsp - status %d", + "initialzation with NetVsp - status %d\n", init_packet->msg.v1_msg. send_recv_buf_complete.status); ret = -EINVAL; @@ -270,7 +270,7 @@ static int netvsc_connect_vsp(struct hv_device *device) net_device = get_outbound_net_device(device); if (!net_device) { dev_err(&device->device, "unable to get net device..." - "device being destroyed?"); + "device being destroyed?\n"); return -ENODEV; } @@ -361,7 +361,7 @@ int netvsc_device_remove(struct hv_device *device) /* Wait for all send completions */ while (atomic_read(&net_device->num_outstanding_sends)) { dev_err(&device->device, - "waiting for %d requests to complete...", + "waiting for %d requests to complete...\n", atomic_read(&net_device->num_outstanding_sends)); udelay(100); } @@ -381,7 +381,7 @@ int netvsc_device_remove(struct hv_device *device) spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* At this point, no one should be accessing netDevice except in here */ - dev_notice(&device->device, "net device safe to remove"); + dev_notice(&device->device, "net device safe to remove\n"); /* Now, we can close the channel safely */ vmbus_close(device->channel); @@ -407,7 +407,7 @@ static void netvsc_send_completion(struct hv_device *device, net_device = get_inbound_net_device(device); if (!net_device) { dev_err(&device->device, "unable to get net device..." - "device being destroyed?"); + "device being destroyed?\n"); return; } @@ -436,7 +436,7 @@ static void netvsc_send_completion(struct hv_device *device, atomic_dec(&net_device->num_outstanding_sends); } else { dev_err(&device->device, "Unknown send completion packet type- " - "%d received!!", nvsp_packet->hdr.msg_type); + "%d received!!\n", nvsp_packet->hdr.msg_type); } } @@ -452,7 +452,7 @@ int netvsc_send(struct hv_device *device, net_device = get_outbound_net_device(device); if (!net_device) { dev_err(&device->device, "net device (%p) shutting down..." - "ignoring outbound packets", net_device); + "ignoring outbound packets\n", net_device); return -ENODEV; } @@ -487,7 +487,7 @@ int netvsc_send(struct hv_device *device, } if (ret != 0) - dev_err(&device->device, "Unable to send packet %p ret %d", + dev_err(&device->device, "Unable to send packet %p ret %d\n", packet, ret); atomic_inc(&net_device->num_outstanding_sends); @@ -520,19 +520,19 @@ retry_send_cmplt: /* no more room...wait a bit and attempt to retry 3 times */ retries++; dev_err(&device->device, "unable to send receive completion pkt" - " (tid %llx)...retrying %d", transaction_id, retries); + " (tid %llx)...retrying %d\n", transaction_id, retries); if (retries < 4) { udelay(100); goto retry_send_cmplt; } else { dev_err(&device->device, "unable to send receive " - "completion pkt (tid %llx)...give up retrying", + "completion pkt (tid %llx)...give up retrying\n", transaction_id); } } else { dev_err(&device->device, "unable to send receive " - "completion pkt - %llx", transaction_id); + "completion pkt - %llx\n", transaction_id); } } @@ -554,7 +554,7 @@ static void netvsc_receive_completion(void *context) net_device = get_inbound_net_device(device); if (!net_device) { dev_err(&device->device, "unable to get net device..." - "device being destroyed?"); + "device being destroyed?\n"); return; } @@ -605,7 +605,7 @@ static void netvsc_receive(struct hv_device *device, net_device = get_inbound_net_device(device); if (!net_device) { dev_err(&device->device, "unable to get net device..." - "device being destroyed?"); + "device being destroyed?\n"); return; } @@ -614,7 +614,7 @@ static void netvsc_receive(struct hv_device *device, * packet */ if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { - dev_err(&device->device, "Unknown packet type received - %d", + dev_err(&device->device, "Unknown packet type received - %d\n", packet->type); return; } @@ -626,7 +626,7 @@ static void netvsc_receive(struct hv_device *device, if (nvsp_packet->hdr.msg_type != NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { dev_err(&device->device, "Unknown nvsp packet type received-" - " %d", nvsp_packet->hdr.msg_type); + " %d\n", nvsp_packet->hdr.msg_type); return; } @@ -634,7 +634,7 @@ static void netvsc_receive(struct hv_device *device, if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { dev_err(&device->device, "Invalid xfer page set id - " - "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, + "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, vmxferpage_packet->xfer_pageset_id); return; } @@ -660,7 +660,7 @@ static void netvsc_receive(struct hv_device *device, */ if (count < 2) { dev_err(&device->device, "Got only %d netvsc pkt...needed " - "%d pkts. Dropping this xfer page packet completely!", + "%d pkts. Dropping this xfer page packet completely!\n", count, vmxferpage_packet->range_cnt + 1); /* Return it to the freelist */ @@ -687,7 +687,7 @@ static void netvsc_receive(struct hv_device *device, if (xferpage_packet->count != vmxferpage_packet->range_cnt) { dev_err(&device->device, "Needed %d netvsc pkts to satisy " - "this xfer page...got %d", + "this xfer page...got %d\n", vmxferpage_packet->range_cnt, xferpage_packet->count); } @@ -785,7 +785,7 @@ static void netvsc_channel_cb(void *context) net_device = get_inbound_net_device(device); if (!net_device) { dev_err(&device->device, "net device (%p) shutting down..." - "ignoring inbound packets", net_device); + "ignoring inbound packets\n", net_device); goto out; } @@ -836,7 +836,7 @@ static void netvsc_channel_cb(void *context) /* Try again next time around */ dev_err(&device->device, "unable to allocate buffer of size " - "(%d)!!", bytes_recvd); + "(%d)!!\n", bytes_recvd); break; } @@ -892,18 +892,18 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) netvsc_channel_cb, device); if (ret != 0) { - dev_err(&device->device, "unable to open channel: %d", ret); + dev_err(&device->device, "unable to open channel: %d\n", ret); goto cleanup; } /* Channel is opened */ - pr_info("hv_netvsc channel opened successfully"); + pr_info("hv_netvsc channel opened successfully\n"); /* Connect with the NetVsp */ ret = netvsc_connect_vsp(device); if (ret != 0) { dev_err(&device->device, - "unable to connect to NetVSP - %d", ret); + "unable to connect to NetVSP - %d\n", ret); goto close; } -- cgit v1.1 From d9871158718778ff060f08cbee0c61eb23041671 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:41 -0700 Subject: staging: hv: convert dev_ to netdev_ in netvsc Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 68 ++++++++++++++++++++++----------------- drivers/staging/hv/rndis_filter.c | 17 ++++++---- 2 files changed, 49 insertions(+), 36 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index ef764e6..82b129b 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "hyperv_net.h" @@ -80,6 +81,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) { struct nvsp_message *revoke_packet; int ret = 0; + struct net_device *ndev = dev_get_drvdata(&net_device->dev->device); /* * If we got a section count, it means we received a @@ -107,7 +109,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) * have a leak rather than continue and a bugchk */ if (ret != 0) { - dev_err(&net_device->dev->device, "unable to send " + netdev_err(ndev, "unable to send " "revoke receive buffer to netvsp\n"); return ret; } @@ -122,7 +124,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) * rather than continue and a bugchk */ if (ret != 0) { - dev_err(&net_device->dev->device, + netdev_err(ndev, "unable to teardown receive buffer's gpadl\n"); return ret; } @@ -151,10 +153,11 @@ static int netvsc_init_recv_buf(struct hv_device *device) int t; struct netvsc_device *net_device; struct nvsp_message *init_packet; + struct net_device *ndev = dev_get_drvdata(&device->device); net_device = get_outbound_net_device(device); if (!net_device) { - dev_err(&device->device, "unable to get net device..." + netdev_err(ndev, "unable to get net device..." "device being destroyed?\n"); return -ENODEV; } @@ -163,7 +166,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, get_order(net_device->recv_buf_size)); if (!net_device->recv_buf) { - dev_err(&device->device, "unable to allocate receive " + netdev_err(ndev, "unable to allocate receive " "buffer of size %d\n", net_device->recv_buf_size); ret = -ENOMEM; goto cleanup; @@ -178,7 +181,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) net_device->recv_buf_size, &net_device->recv_buf_gpadl_handle); if (ret != 0) { - dev_err(&device->device, + netdev_err(ndev, "unable to establish receive buffer's gpadl\n"); goto cleanup; } @@ -202,7 +205,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) { - dev_err(&device->device, + netdev_err(ndev, "unable to send receive buffer's gpadl to netvsp\n"); goto cleanup; } @@ -214,7 +217,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) /* Check the response */ if (init_packet->msg.v1_msg. send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { - dev_err(&device->device, "Unable to complete receive buffer " + netdev_err(ndev, "Unable to complete receive buffer " "initialzation with NetVsp - status %d\n", init_packet->msg.v1_msg. send_recv_buf_complete.status); @@ -266,10 +269,11 @@ static int netvsc_connect_vsp(struct hv_device *device) struct netvsc_device *net_device; struct nvsp_message *init_packet; int ndis_version; + struct net_device *ndev = dev_get_drvdata(&device->device); net_device = get_outbound_net_device(device); if (!net_device) { - dev_err(&device->device, "unable to get net device..." + netdev_err(ndev, "unable to get net device..." "device being destroyed?\n"); return -ENODEV; } @@ -360,7 +364,7 @@ int netvsc_device_remove(struct hv_device *device) /* Wait for all send completions */ while (atomic_read(&net_device->num_outstanding_sends)) { - dev_err(&device->device, + dev_info(&device->device, "waiting for %d requests to complete...\n", atomic_read(&net_device->num_outstanding_sends)); udelay(100); @@ -403,10 +407,11 @@ static void netvsc_send_completion(struct hv_device *device, struct netvsc_device *net_device; struct nvsp_message *nvsp_packet; struct hv_netvsc_packet *nvsc_packet; + struct net_device *ndev = dev_get_drvdata(&device->device); net_device = get_inbound_net_device(device); if (!net_device) { - dev_err(&device->device, "unable to get net device..." + netdev_err(ndev, "unable to get net device..." "device being destroyed?\n"); return; } @@ -435,7 +440,7 @@ static void netvsc_send_completion(struct hv_device *device, atomic_dec(&net_device->num_outstanding_sends); } else { - dev_err(&device->device, "Unknown send completion packet type- " + netdev_err(ndev, "Unknown send completion packet type- " "%d received!!\n", nvsp_packet->hdr.msg_type); } @@ -446,12 +451,12 @@ int netvsc_send(struct hv_device *device, { struct netvsc_device *net_device; int ret = 0; - struct nvsp_message sendMessage; + struct net_device *ndev = dev_get_drvdata(&device->device); net_device = get_outbound_net_device(device); if (!net_device) { - dev_err(&device->device, "net device (%p) shutting down..." + netdev_err(ndev, "net device (%p) shutting down..." "ignoring outbound packets\n", net_device); return -ENODEV; } @@ -487,7 +492,7 @@ int netvsc_send(struct hv_device *device, } if (ret != 0) - dev_err(&device->device, "Unable to send packet %p ret %d\n", + netdev_err(ndev, "Unable to send packet %p ret %d\n", packet, ret); atomic_inc(&net_device->num_outstanding_sends); @@ -500,6 +505,7 @@ static void netvsc_send_recv_completion(struct hv_device *device, struct nvsp_message recvcompMessage; int retries = 0; int ret; + struct net_device *ndev = dev_get_drvdata(&device->device); recvcompMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; @@ -519,19 +525,19 @@ retry_send_cmplt: } else if (ret == -EAGAIN) { /* no more room...wait a bit and attempt to retry 3 times */ retries++; - dev_err(&device->device, "unable to send receive completion pkt" + netdev_err(ndev, "unable to send receive completion pkt" " (tid %llx)...retrying %d\n", transaction_id, retries); if (retries < 4) { udelay(100); goto retry_send_cmplt; } else { - dev_err(&device->device, "unable to send receive " + netdev_err(ndev, "unable to send receive " "completion pkt (tid %llx)...give up retrying\n", transaction_id); } } else { - dev_err(&device->device, "unable to send receive " + netdev_err(ndev, "unable to send receive " "completion pkt - %llx\n", transaction_id); } } @@ -545,6 +551,7 @@ static void netvsc_receive_completion(void *context) u64 transaction_id = 0; bool fsend_receive_comp = false; unsigned long flags; + struct net_device *ndev = dev_get_drvdata(&device->device); /* * Even though it seems logical to do a GetOutboundNetDevice() here to @@ -553,7 +560,7 @@ static void netvsc_receive_completion(void *context) */ net_device = get_inbound_net_device(device); if (!net_device) { - dev_err(&device->device, "unable to get net device..." + netdev_err(ndev, "unable to get net device..." "device being destroyed?\n"); return; } @@ -599,12 +606,13 @@ static void netvsc_receive(struct hv_device *device, int i, j; int count = 0, bytes_remain = 0; unsigned long flags; + struct net_device *ndev = dev_get_drvdata(&device->device); LIST_HEAD(listHead); net_device = get_inbound_net_device(device); if (!net_device) { - dev_err(&device->device, "unable to get net device..." + netdev_err(ndev, "unable to get net device..." "device being destroyed?\n"); return; } @@ -614,7 +622,7 @@ static void netvsc_receive(struct hv_device *device, * packet */ if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { - dev_err(&device->device, "Unknown packet type received - %d\n", + netdev_err(ndev, "Unknown packet type received - %d\n", packet->type); return; } @@ -625,7 +633,7 @@ static void netvsc_receive(struct hv_device *device, /* Make sure this is a valid nvsp packet */ if (nvsp_packet->hdr.msg_type != NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { - dev_err(&device->device, "Unknown nvsp packet type received-" + netdev_err(ndev, "Unknown nvsp packet type received-" " %d\n", nvsp_packet->hdr.msg_type); return; } @@ -633,7 +641,7 @@ static void netvsc_receive(struct hv_device *device, vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet; if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { - dev_err(&device->device, "Invalid xfer page set id - " + netdev_err(ndev, "Invalid xfer page set id - " "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, vmxferpage_packet->xfer_pageset_id); return; @@ -659,7 +667,7 @@ static void netvsc_receive(struct hv_device *device, * some of the xfer page packet ranges... */ if (count < 2) { - dev_err(&device->device, "Got only %d netvsc pkt...needed " + netdev_err(ndev, "Got only %d netvsc pkt...needed " "%d pkts. Dropping this xfer page packet completely!\n", count, vmxferpage_packet->range_cnt + 1); @@ -686,7 +694,7 @@ static void netvsc_receive(struct hv_device *device, xferpage_packet->count = count - 1; if (xferpage_packet->count != vmxferpage_packet->range_cnt) { - dev_err(&device->device, "Needed %d netvsc pkts to satisy " + netdev_err(ndev, "Needed %d netvsc pkts to satisy " "this xfer page...got %d\n", vmxferpage_packet->range_cnt, xferpage_packet->count); } @@ -775,6 +783,7 @@ static void netvsc_channel_cb(void *context) struct vmpacket_descriptor *desc; unsigned char *buffer; int bufferlen = NETVSC_PACKET_SIZE; + struct net_device *ndev = dev_get_drvdata(&device->device); packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), GFP_ATOMIC); @@ -784,7 +793,7 @@ static void netvsc_channel_cb(void *context) net_device = get_inbound_net_device(device); if (!net_device) { - dev_err(&device->device, "net device (%p) shutting down..." + netdev_err(ndev, "net device (%p) shutting down..." "ignoring inbound packets\n", net_device); goto out; } @@ -805,7 +814,7 @@ static void netvsc_channel_cb(void *context) break; default: - dev_err(&device->device, + netdev_err(ndev, "unhandled packet type %d, " "tid %llx len %d\n", desc->type, request_id, @@ -834,7 +843,7 @@ static void netvsc_channel_cb(void *context) buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { /* Try again next time around */ - dev_err(&device->device, + netdev_err(ndev, "unable to allocate buffer of size " "(%d)!!\n", bytes_recvd); break; @@ -861,6 +870,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) ((struct netvsc_device_info *)additional_info)->ring_size; struct netvsc_device *net_device; struct hv_netvsc_packet *packet, *pos; + struct net_device *ndev = dev_get_drvdata(&device->device); net_device = alloc_net_device(device); if (!net_device) { @@ -892,7 +902,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) netvsc_channel_cb, device); if (ret != 0) { - dev_err(&device->device, "unable to open channel: %d\n", ret); + netdev_err(ndev, "unable to open channel: %d\n", ret); goto cleanup; } @@ -902,7 +912,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) /* Connect with the NetVsp */ ret = netvsc_connect_vsp(device); if (ret != 0) { - dev_err(&device->device, + netdev_err(ndev, "unable to connect to NetVSP - %d\n", ret); goto close; } diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 8416bf2..20e673d 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -249,6 +249,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev, struct rndis_request *request = NULL; bool found = false; unsigned long flags; + struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device); spin_lock_irqsave(&dev->request_lock, flags); list_for_each_entry(request, &dev->req_list, list_ent) { @@ -269,7 +270,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev, memcpy(&request->response_msg, resp, resp->msg_len); } else { - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "rndis response buffer overflow " "detected (size %u max %zu)\n", resp->msg_len, @@ -289,7 +290,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev, complete(&request->wait_event); } else { - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "no rndis request found for this response " "(id 0x%x res type 0x%x)\n", resp->msg.init_complete.req_id, @@ -349,20 +350,21 @@ int rndis_filter_receive(struct hv_device *dev, struct rndis_device *rndis_dev; struct rndis_message rndis_msg; struct rndis_message *rndis_hdr; + struct net_device *ndev = dev_get_drvdata(&dev->device); if (!net_dev) return -EINVAL; /* Make sure the rndis device state is initialized */ if (!net_dev->extension) { - dev_err(&dev->device, "got rndis message but no rndis device - " + netdev_err(ndev, "got rndis message but no rndis device - " "dropping this message!\n"); return -ENODEV; } rndis_dev = (struct rndis_device *)net_dev->extension; if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { - dev_err(&dev->device, "got rndis message but rndis device " + netdev_err(ndev, "got rndis message but rndis device " "uninitialized...dropping this message!\n"); return -ENODEV; } @@ -376,7 +378,7 @@ int rndis_filter_receive(struct hv_device *dev, /* Make sure we got a valid rndis message */ if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) && (rndis_hdr->msg_len > sizeof(struct rndis_message))) { - dev_err(&dev->device, "incoming rndis message buffer overflow " + netdev_err(ndev, "incoming rndis message buffer overflow " "detected (got %u, max %zu)..marking it an error!\n", rndis_hdr->msg_len, sizeof(struct rndis_message)); @@ -409,7 +411,7 @@ int rndis_filter_receive(struct hv_device *dev, rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); break; default: - dev_err(&dev->device, + netdev_err(ndev, "unhandled rndis message (type %u len %u)\n", rndis_msg.ndis_msg_type, rndis_msg.msg_len); @@ -505,6 +507,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, struct rndis_set_complete *set_complete; u32 status; int ret, t; + struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device); request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + @@ -530,7 +533,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "timeout before we got a set response...\n"); /* * We can't deallocate the request since we may still receive a -- cgit v1.1 From c4b6a2eaf1c14810a4803d658f68614365978738 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:42 -0700 Subject: staging: hv: fix a kernel warning in netvsc_linkstatus_callback() netif_notify_peers() caused a kernel warning in netvsc_linkstatus_callback(), because netvsc_linkstatus_callback() is within IRQ context. So we move the first call to netif_notify_peers() into queued work as well, but with zero delay. In addition to "staging-next", this should also be back-ported to stable kernels 2.6.32 and later. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 30a0cb2..e6513be 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -214,8 +214,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, if (status == 1) { netif_carrier_on(net); netif_wake_queue(net); - netif_notify_peers(net); ndev_ctx = netdev_priv(net); + schedule_delayed_work(&ndev_ctx->dwork, 0); schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); } else { netif_carrier_off(net); -- cgit v1.1 From 692e084e773b76c30a3e5d823db131ed1a15924a Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:43 -0700 Subject: staging: hv: re-order the code in netvsc_probe() Re-order the code in netvsc_probe() to prevent a guest crash caused by packets possibly received from NetVSP before call to register_netdev(). Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index e6513be..b49a08f 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -348,19 +348,6 @@ static int netvsc_probe(struct hv_device *dev) dev_set_drvdata(&dev->device, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); - /* Notify the netvsc driver of the new device */ - device_info.ring_size = ring_size; - ret = rndis_filter_device_add(dev, &device_info); - if (ret != 0) { - free_netdev(net); - dev_set_drvdata(&dev->device, NULL); - return ret; - } - - netif_carrier_on(net); - - memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); - net->netdev_ops = &device_ops; /* TODO: Add GSO and Checksum offload */ @@ -372,11 +359,26 @@ static int netvsc_probe(struct hv_device *dev) ret = register_netdev(net); if (ret != 0) { - /* Remove the device and release the resource */ - rndis_filter_device_remove(dev); + pr_err("Unable to register netdev.\n"); free_netdev(net); + goto out; } + /* Notify the netvsc driver of the new device */ + device_info.ring_size = ring_size; + ret = rndis_filter_device_add(dev, &device_info); + if (ret != 0) { + netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); + unregister_netdev(net); + free_netdev(net); + dev_set_drvdata(&dev->device, NULL); + return ret; + } + memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); + + netif_carrier_on(net); + +out: return ret; } -- cgit v1.1 From 7db1d946c4db748b631fe4885110349cc259987f Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:44 -0700 Subject: staging: hv: fix counting of #outstanding-sends in failed sends If the packet failed to be sent, we shouldn't count it as the number of outstanding sends. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 82b129b..efbc8a0 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -494,8 +494,9 @@ int netvsc_send(struct hv_device *device, if (ret != 0) netdev_err(ndev, "Unable to send packet %p ret %d\n", packet, ret); + else + atomic_inc(&net_device->num_outstanding_sends); - atomic_inc(&net_device->num_outstanding_sends); return ret; } -- cgit v1.1 From 8a5f9edc4dd6c1f9fb2446a36e7cd44b79412271 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:45 -0700 Subject: staging: hv: fix counting of available buffer slots when send fails Because the number of available buffer slots doesn't decrease for failed sends, we should not call netvsc_xmit_completion(), which increase the count of available slots. In this failed case, just free the memory is enough. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index b49a08f..81e3c49 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -190,7 +190,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) } else { /* we are shutting down or bus overloaded, just drop packet */ net->stats.tx_dropped++; - netvsc_xmit_completion(packet); + kfree(packet); + dev_kfree_skb_any(skb); } return NETDEV_TX_OK; -- cgit v1.1 From bf769375c9175b29fe72b10394888e0090c6b133 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:46 -0700 Subject: staging: hv: fix the return status of netvsc_start_xmit() Fix the return status, so the upper layer will retry if transmission fails. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 81e3c49..30b9c80 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -140,12 +140,12 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) (num_pages * sizeof(struct hv_page_buffer)) + sizeof(struct rndis_filter_packet), GFP_ATOMIC); if (!packet) { - /* out of memory, silently drop packet */ + /* out of memory, drop packet */ netdev_err(net, "unable to allocate hv_netvsc_packet\n"); dev_kfree_skb(skb); net->stats.tx_dropped++; - return NETDEV_TX_OK; + return NETDEV_TX_BUSY; } packet->extension = (void *)(unsigned long)packet + @@ -194,7 +194,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) dev_kfree_skb_any(skb); } - return NETDEV_TX_OK; + return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK; } /* -- cgit v1.1 From 669c1fc61679f7e85f467c852bfe7b6c9dd75d25 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:47 -0700 Subject: staging: hv: fix the page buffer when rndis data go across page boundary In rndis_filter_receive_data(), we need to drop the 0th page and move the rest of pages forward if the rndis data go across page boundary, otherwise the page offset will overflow. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 20e673d..b325345 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -323,6 +323,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev, { struct rndis_packet *rndis_pkt; u32 data_offset; + int i; rndis_pkt = &msg->msg.pkt; @@ -338,6 +339,15 @@ static void rndis_filter_receive_data(struct rndis_device *dev, pkt->page_buf[0].offset += data_offset; pkt->page_buf[0].len -= data_offset; + /* Drop the 0th page, if rndis data go beyond page boundary */ + if (pkt->page_buf[0].offset >= PAGE_SIZE) { + pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE; + pkt->page_buf[1].len -= pkt->page_buf[1].offset; + pkt->page_buf_cnt--; + for (i = 0; i < pkt->page_buf_cnt; i++) + pkt->page_buf[i] = pkt->page_buf[i+1]; + } + pkt->is_data_pkt = true; netvsc_recv_callback(dev->net_dev->dev, pkt); -- cgit v1.1 From 8bff33ab417f246dac4ab9835be6894eaddfb546 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 1 Sep 2011 12:19:48 -0700 Subject: staging: hv: fix some typos in netvsc.c Reported-by: Joe Perches Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index efbc8a0..115629f 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -218,7 +218,7 @@ static int netvsc_init_recv_buf(struct hv_device *device) if (init_packet->msg.v1_msg. send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { netdev_err(ndev, "Unable to complete receive buffer " - "initialzation with NetVsp - status %d\n", + "initialization with NetVsp - status %d\n", init_packet->msg.v1_msg. send_recv_buf_complete.status); ret = -EINVAL; @@ -695,7 +695,7 @@ static void netvsc_receive(struct hv_device *device, xferpage_packet->count = count - 1; if (xferpage_packet->count != vmxferpage_packet->range_cnt) { - netdev_err(ndev, "Needed %d netvsc pkts to satisy " + netdev_err(ndev, "Needed %d netvsc pkts to satisfy " "this xfer page...got %d\n", vmxferpage_packet->range_cnt, xferpage_packet->count); } -- cgit v1.1 From b2451a4907fdcd718c3580d1e64d75fde04148fa Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 2 Sep 2011 08:55:41 -0700 Subject: Staging: hv: Update TODO file Based on input from Greg, update the TODO file. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/TODO | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index 582fd4a..7c9a93f 100644 --- a/drivers/staging/hv/TODO +++ b/drivers/staging/hv/TODO @@ -1,14 +1,11 @@ TODO: - - fix remaining checkpatch warnings and errors - audit the vmbus to verify it is working properly with the driver model - - see if the vmbus can be merged with the other virtual busses - in the kernel - audit the network driver - checking for carrier inside open is wrong, network device API confusion?? - - audit the block driver - audit the scsi driver Please send patches for this code to Greg Kroah-Hartman , -Hank Janssen , and Haiyang Zhang . +Hank Janssen , Haiyang Zhang , +K. Y. Srinivasan -- cgit v1.1 From fd776ba9abdb6a89aa1ef500d7046caa35a0905a Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 2 Sep 2011 18:25:56 +0200 Subject: Staging: hv: vmbus: Show the modalias in /sys/bus/vmbus/devices/*/ Show a modalias file in /sys/bus/vmbus/devices/*/ Add a helper function to print the same content in modalias and uevent. Signed-off-by: Olaf Hering Acked-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index cd43ddd..c0f3b7a 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -93,6 +93,14 @@ static void get_channel_info(struct hv_device *device, debug_info.outbound.bytes_avail_towrite; } +#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2) +static void print_alias_name(struct hv_device *hv_dev, char *alias_name) +{ + int i; + for (i = 0; i < VMBUS_ALIAS_LEN; i += 2) + sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); +} + /* * vmbus_show_device_attr - Show the device attribute in sysfs. * @@ -105,6 +113,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_device_info device_info; + char alias_name[VMBUS_ALIAS_LEN + 1]; memset(&device_info, 0, sizeof(struct hv_device_info)); @@ -148,6 +157,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev, device_info.chn_instance.b[13], device_info.chn_instance.b[14], device_info.chn_instance.b[15]); + } else if (!strcmp(dev_attr->attr.name, "modalias")) { + print_alias_name(hv_dev, alias_name); + return sprintf(buf, "vmbus:%s\n", alias_name); } else if (!strcmp(dev_attr->attr.name, "state")) { return sprintf(buf, "%d\n", device_info.chn_state); } else if (!strcmp(dev_attr->attr.name, "id")) { @@ -204,6 +216,7 @@ static struct device_attribute vmbus_device_attrs[] = { __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), + __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), @@ -242,12 +255,10 @@ static struct device_attribute vmbus_device_attrs[] = { static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) { struct hv_device *dev = device_to_hv_device(device); - int i, ret; - char alias_name[((sizeof((struct hv_vmbus_device_id *)0)->guid) + 1) * 2]; - - for (i = 0; i < ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2); i += 2) - sprintf(&alias_name[i], "%02x", dev->dev_type.b[i/2]); + int ret; + char alias_name[VMBUS_ALIAS_LEN + 1]; + print_alias_name(dev, alias_name); ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name); return ret; } -- cgit v1.1 From cf55f4a8b6243b42fb91c56d1421db0d36d60f96 Mon Sep 17 00:00:00 2001 From: Mike Sterling Date: Tue, 6 Sep 2011 16:10:55 -0700 Subject: Staging: hv: Add support for >2 TB LUN in storage driver. If a LUN larger than 2 TB is attached to a Linux VM on Hyper-V, we currently report a maximum size of 2 TB. This patch resolves the issue in hv_storvsc. Thanks to Robert Scheck for reporting the issue. Reported-by: Robert Scheck Signed-off-by: Mike Sterling Signed-off-by: K.Y. Srinivasan Signed-off-by: Haiyang Zhang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 3686d10..b0c4e56 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -232,6 +232,7 @@ struct vstor_packet { #define STORVSC_MAX_LUNS_PER_TARGET 64 #define STORVSC_MAX_TARGETS 1 #define STORVSC_MAX_CHANNELS 1 +#define STORVSC_MAX_CMD_LEN 16 struct hv_storvsc_request; @@ -1440,6 +1441,8 @@ static int storvsc_probe(struct hv_device *device) host->max_id = STORVSC_MAX_TARGETS; /* max # of channels */ host->max_channel = STORVSC_MAX_CHANNELS - 1; + /* max cmd length */ + host->max_cmd_len = STORVSC_MAX_CMD_LEN; /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); -- cgit v1.1 From f2c73011117f6b45dea01f5450285405b5e88efb Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 8 Sep 2011 07:24:12 -0700 Subject: Staging: hv: vmbus: Rename vmbus_child_device_create The vmbus devices are NOT child devices; rename vmbus_child_device_create to reflect this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 2 +- drivers/staging/hv/hyperv_vmbus.h | 2 +- drivers/staging/hv/vmbus_drv.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 11beb41c..f99b944 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -383,7 +383,7 @@ static void vmbus_process_offer(struct work_struct *work) * We need to set the DeviceObject field before calling * vmbus_child_dev_add() */ - newchannel->device_obj = vmbus_child_device_create( + newchannel->device_obj = vmbus_device_create( &newchannel->offermsg.offer.if_type, &newchannel->offermsg.offer.if_instance, newchannel); diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h index 16ca90d..e97e2cf 100644 --- a/drivers/staging/hv/hyperv_vmbus.h +++ b/drivers/staging/hv/hyperv_vmbus.h @@ -601,7 +601,7 @@ extern struct vmbus_connection vmbus_connection; /* General vmbus interface */ -struct hv_device *vmbus_child_device_create(uuid_le *type, +struct hv_device *vmbus_device_create(uuid_le *type, uuid_le *instance, struct vmbus_channel *channel); diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c0f3b7a..382baee 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -594,10 +594,10 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) EXPORT_SYMBOL_GPL(vmbus_driver_unregister); /* - * vmbus_child_device_create - Creates and registers a new child device + * vmbus_device_create - Creates and registers a new child device * on the vmbus. */ -struct hv_device *vmbus_child_device_create(uuid_le *type, +struct hv_device *vmbus_device_create(uuid_le *type, uuid_le *instance, struct vmbus_channel *channel) { -- cgit v1.1 From 22794281974f9ba7770615191c382cca03067736 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 8 Sep 2011 07:24:13 -0700 Subject: Staging: hv: vmbus: Rename vmbus_child_device_register The vmbus devices are NOT child devices; rename vmbus_child_device_register to reflect this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 2 +- drivers/staging/hv/hyperv_vmbus.h | 2 +- drivers/staging/hv/vmbus_drv.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index f99b944..a927046 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -393,7 +393,7 @@ static void vmbus_process_offer(struct work_struct *work) * binding which eventually invokes the device driver's AddDevice() * method. */ - ret = vmbus_child_device_register(newchannel->device_obj); + ret = vmbus_device_register(newchannel->device_obj); if (ret != 0) { pr_err("unable to add child device object (relid %d)\n", newchannel->offermsg.child_relid); diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h index e97e2cf..b2dfcd6 100644 --- a/drivers/staging/hv/hyperv_vmbus.h +++ b/drivers/staging/hv/hyperv_vmbus.h @@ -605,7 +605,7 @@ struct hv_device *vmbus_device_create(uuid_le *type, uuid_le *instance, struct vmbus_channel *channel); -int vmbus_child_device_register(struct hv_device *child_device_obj); +int vmbus_device_register(struct hv_device *child_device_obj); void vmbus_child_device_unregister(struct hv_device *device_obj); /* static void */ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 382baee..6d54ea1 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -619,9 +619,9 @@ struct hv_device *vmbus_device_create(uuid_le *type, } /* - * vmbus_child_device_register - Register the child device + * vmbus_device_register - Register the child device */ -int vmbus_child_device_register(struct hv_device *child_device_obj) +int vmbus_device_register(struct hv_device *child_device_obj) { int ret = 0; -- cgit v1.1 From 696453ba2830501274b17a5953c40f7794a56df0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 8 Sep 2011 07:24:14 -0700 Subject: Staging: hv: vmbus: Rename vmbus_child_device_unregister The vmbus devices are NOT child devices; rename vmbus_child_device_unregister to reflect this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 2 +- drivers/staging/hv/hyperv_vmbus.h | 2 +- drivers/staging/hv/vmbus_drv.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index a927046..60ce1d1 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -333,7 +333,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work) struct vmbus_channel, work); - vmbus_child_device_unregister(channel->device_obj); + vmbus_device_unregister(channel->device_obj); } /* diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h index b2dfcd6..3d2d836 100644 --- a/drivers/staging/hv/hyperv_vmbus.h +++ b/drivers/staging/hv/hyperv_vmbus.h @@ -606,7 +606,7 @@ struct hv_device *vmbus_device_create(uuid_le *type, struct vmbus_channel *channel); int vmbus_device_register(struct hv_device *child_device_obj); -void vmbus_child_device_unregister(struct hv_device *device_obj); +void vmbus_device_unregister(struct hv_device *device_obj); /* static void */ /* VmbusChildDeviceDestroy( */ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 6d54ea1..375e451 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -650,10 +650,10 @@ int vmbus_device_register(struct hv_device *child_device_obj) } /* - * vmbus_child_device_unregister - Remove the specified child device + * vmbus_device_unregister - Remove the specified child device * from the vmbus. */ -void vmbus_child_device_unregister(struct hv_device *device_obj) +void vmbus_device_unregister(struct hv_device *device_obj) { /* * Kick off the process of unregistering the device. -- cgit v1.1 From 66e60413db488e4830286220152ae63d31c32a6a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 8 Sep 2011 07:24:15 -0700 Subject: Staging: hv: vmbus: Cleanup dated comments in channel_mgmt.c Cleanup dated comments in channel_mgmt.c. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 60ce1d1..c68e5fa 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -433,9 +433,6 @@ static void vmbus_process_offer(struct work_struct *work) /* * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. * - * We ignore all offers except network and storage offers. For each network and - * storage offers, we create a channel object and queue a work item to the - * channel object to process the offer synchronously */ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) { -- cgit v1.1 From 3037a7b61fa63160f2bd76555aa9ae59c6f71faf Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:37 -0700 Subject: Staging: hv: vmbus: Introduce a utility function to match hv_vmbus_device_id Introduce a utility function to match hv_vmbus_device_id. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 375e451..77f4373 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -272,6 +272,22 @@ static inline bool is_null_guid(const __u8 *guid) return true; } +/* + * Return a matching hv_vmbus_device_id pointer. + * If there is no match, return NULL. + */ +static const struct hv_vmbus_device_id *hv_vmbus_get_id( + const struct hv_vmbus_device_id *id, + __u8 *guid) +{ + for (; !is_null_guid(id->guid); id++) + if (!memcmp(&id->guid, guid, sizeof(uuid_le))) + return id; + + return NULL; +} + + /* * vmbus_match - Attempt to match the specified device to the specified driver @@ -280,12 +296,9 @@ static int vmbus_match(struct device *device, struct device_driver *driver) { struct hv_driver *drv = drv_to_hv_drv(driver); struct hv_device *hv_dev = device_to_hv_device(device); - const struct hv_vmbus_device_id *id_array = drv->id_table; - for (; !is_null_guid(id_array->guid); id_array++) - if (!memcmp(&id_array->guid, &hv_dev->dev_type.b, - sizeof(uuid_le))) - return 1; + if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b)) + return 1; return 0; } -- cgit v1.1 From 84946899bd50035c50d88da9da809aa25de60471 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:38 -0700 Subject: Staging: hv: vmbus: Change the signature of struct hv_driver probe function In preparation to leveraging the driver_data field in struct hv_vmbus_device_id, change the signature of struct hv_driver probe function. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 3 ++- drivers/staging/hv/hv_util.c | 3 ++- drivers/staging/hv/hyperv.h | 2 +- drivers/staging/hv/netvsc_drv.c | 3 ++- drivers/staging/hv/storvsc_drv.c | 3 ++- drivers/staging/hv/vmbus_drv.c | 4 +++- 6 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index dbb04ee..5ff8a03 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -823,7 +823,8 @@ static int mousevsc_on_device_remove(struct hv_device *device) } -static int mousevsc_probe(struct hv_device *dev) +static int mousevsc_probe(struct hv_device *dev, + const struct hv_vmbus_device_id *dev_id) { int ret = 0; diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index 6039217..d9460fdd 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -239,7 +239,8 @@ static void heartbeat_onchannelcallback(void *context) * The devices managed by the util driver don't need any additional * setup. */ -static int util_probe(struct hv_device *dev) +static int util_probe(struct hv_device *dev, + const struct hv_vmbus_device_id *dev_id) { return 0; } diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index c249811..caa3a7b 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -810,7 +810,7 @@ struct hv_driver { struct device_driver driver; - int (*probe)(struct hv_device *); + int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *); int (*remove)(struct hv_device *); void (*shutdown)(struct hv_device *); diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 30b9c80..d06cde29 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -329,7 +329,8 @@ static void netvsc_send_garp(struct work_struct *w) } -static int netvsc_probe(struct hv_device *dev) +static int netvsc_probe(struct hv_device *dev, + const struct hv_vmbus_device_id *dev_id) { struct net_device *net = NULL; struct net_device_context *net_device_ctx; diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index b0c4e56..fff1e5b 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1380,7 +1380,8 @@ MODULE_DEVICE_TABLE(vmbus, id_table); * storvsc_probe - Add a new device for this driver */ -static int storvsc_probe(struct hv_device *device) +static int storvsc_probe(struct hv_device *device, + const struct hv_vmbus_device_id *dev_id) { int ret; struct Scsi_Host *host; diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 77f4373..2fccb1f 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -312,9 +312,11 @@ static int vmbus_probe(struct device *child_device) struct hv_driver *drv = drv_to_hv_drv(child_device->driver); struct hv_device *dev = device_to_hv_device(child_device); + const struct hv_vmbus_device_id *dev_id; + dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b); if (drv->probe) { - ret = drv->probe(dev); + ret = drv->probe(dev, dev_id); if (ret != 0) pr_err("probe failed for device %s (%d)\n", dev_name(child_device), ret); -- cgit v1.1 From ef52a81bf5b229d74b76a25c5de22ae10e1fbb77 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:39 -0700 Subject: Staging: hv: storvsc: Use the driver_data to identify ide Use the driver_data to identify ide devices in storvsc_probe(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index fff1e5b..b996293 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1359,17 +1359,20 @@ static struct scsi_host_template scsi_driver = { .dma_boundary = PAGE_SIZE-1, }; -/* - * The storvsc_probe function assumes that the IDE guid - * is the second entry. - */ +enum { + SCSI_GUID, + IDE_GUID, +}; + static const struct hv_vmbus_device_id id_table[] = { /* SCSI guid */ { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) }, + 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) + .driver_data = SCSI_GUID }, /* IDE guid */ { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) }, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) + .driver_data = IDE_GUID }, { }, }; @@ -1387,15 +1390,10 @@ static int storvsc_probe(struct hv_device *device, struct Scsi_Host *host; struct hv_host_device *host_dev; struct storvsc_device_info device_info; - bool dev_is_ide; + bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); int path = 0; int target = 0; - if (!memcmp(&device->dev_type.b, id_table[1].guid, sizeof(uuid_le))) - dev_is_ide = true; - else - dev_is_ide = false; - host = scsi_host_alloc(&scsi_driver, sizeof(struct hv_host_device)); if (!host) -- cgit v1.1 From ab101e86d0f2c00c11aec5b16e27246ccecb0870 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:40 -0700 Subject: Staging: hv: vmbus: Introduce functions for setting and getting driver data Introduce vmbus specific wrapper functions to set/get driver specific data. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index caa3a7b..91e557b 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -843,6 +843,15 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) return container_of(d, struct hv_driver, driver); } +static inline void hv_set_drvdata(struct hv_device *dev, void *data) +{ + dev_set_drvdata(&dev->device, data); +} + +static inline void *hv_get_drvdata(struct hv_device *dev) +{ + return dev_get_drvdata(&dev->device); +} /* Vmbus interface */ #define vmbus_driver_register(driver) \ -- cgit v1.1 From d4372179c85b50cf0a468c1d573113056b0c46a0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:44 -0700 Subject: Staging: hv: vmbus: Cleanup vmbus_remove() vmbus_remove() cannot fail; clean it up accordingly. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 2fccb1f..466425a 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -334,22 +334,14 @@ static int vmbus_probe(struct device *child_device) */ static int vmbus_remove(struct device *child_device) { - int ret; - struct hv_driver *drv; - + struct hv_driver *drv = drv_to_hv_drv(child_device->driver); struct hv_device *dev = device_to_hv_device(child_device); - if (child_device->driver) { - drv = drv_to_hv_drv(child_device->driver); - - if (drv->remove) { - ret = drv->remove(dev); - } else { - pr_err("remove not set for driver %s\n", - dev_name(child_device)); - ret = -ENODEV; - } - } + if (drv->remove) + drv->remove(dev); + else + pr_err("remove not set for driver %s\n", + dev_name(child_device)); return 0; } -- cgit v1.1 From 6e4198ce18859953019d8f32f71e3a7aa309b72d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:45 -0700 Subject: Staging: hv: storvsc: Get rid of storvsc_dev_add() by inlining the code Get rid of storvsc_dev_add() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 58 ++++++++++------------------------------ 1 file changed, 14 insertions(+), 44 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index b996293..2210c8c 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -651,41 +651,6 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) return ret; } -static int storvsc_dev_add(struct hv_device *device, - void *additional_info) -{ - struct storvsc_device *stor_device; - struct storvsc_device_info *device_info; - int ret = 0; - - device_info = (struct storvsc_device_info *)additional_info; - stor_device = alloc_stor_device(device); - if (!stor_device) - return -ENOMEM; - - /* Save the channel properties to our storvsc channel */ - - /* - * If we support more than 1 scsi channel, we need to set the - * port number here to the scsi channel but how do we get the - * scsi channel prior to the bus scan. - * - * The host does not support this. - */ - - stor_device->port_number = device_info->port_number; - /* Send it back up */ - ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size); - if (ret) { - kfree(stor_device); - return ret; - } - device_info->path_id = stor_device->path_id; - device_info->target_id = stor_device->target_id; - - return ret; -} - static int storvsc_dev_remove(struct hv_device *device) { struct storvsc_device *stor_device; @@ -1389,10 +1354,10 @@ static int storvsc_probe(struct hv_device *device, int ret; struct Scsi_Host *host; struct hv_host_device *host_dev; - struct storvsc_device_info device_info; bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); int path = 0; int target = 0; + struct storvsc_device *stor_device; host = scsi_host_alloc(&scsi_driver, sizeof(struct hv_host_device)); @@ -1417,22 +1382,27 @@ static int storvsc_probe(struct hv_device *device, return -ENOMEM; } - device_info.port_number = host->host_no; - device_info.ring_buffer_size = storvsc_ringbuffer_size; - /* Call to the vsc driver to add the device */ - ret = storvsc_dev_add(device, (void *)&device_info); + stor_device = alloc_stor_device(device); + if (!stor_device) { + kmem_cache_destroy(host_dev->request_pool); + scsi_host_put(host); + return -ENOMEM; + } - if (ret != 0) { + stor_device->port_number = host->host_no; + ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); + if (ret) { kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); - return -ENODEV; + kfree(stor_device); + return ret; } if (dev_is_ide) storvsc_get_ide_info(device, &target, &path); - host_dev->path = device_info.path_id; - host_dev->target = device_info.target_id; + host_dev->path = stor_device->path_id; + host_dev->target = stor_device->target_id; /* max # of devices per target */ host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; -- cgit v1.1 From a13d35ab9fdcc8e40af570039120a35179426c08 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:46 -0700 Subject: Staging: hv: storvsc: Get rid of alloc_stor_device() by inlining the code Get rid of alloc_stor_device() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 2210c8c..ce8652e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -332,23 +332,6 @@ static inline void storvsc_wait_to_drain(struct storvsc_device *dev) dev->drain_notify = false; } -static inline struct storvsc_device *alloc_stor_device(struct hv_device *device) -{ - struct storvsc_device *stor_device; - - stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); - if (!stor_device) - return NULL; - - stor_device->destroy = false; - init_waitqueue_head(&stor_device->waiting_to_drain); - stor_device->device = device; - device->ext = stor_device; - - return stor_device; -} - - static inline struct storvsc_device *get_in_stor_device( struct hv_device *device) { @@ -1382,13 +1365,18 @@ static int storvsc_probe(struct hv_device *device, return -ENOMEM; } - stor_device = alloc_stor_device(device); + stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); if (!stor_device) { kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); return -ENOMEM; } + stor_device->destroy = false; + init_waitqueue_head(&stor_device->waiting_to_drain); + stor_device->device = device; + device->ext = stor_device; + stor_device->port_number = host->host_no; ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); if (ret) { -- cgit v1.1 From f810d592a29314ade8cce29f8dac858c90a50409 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:47 -0700 Subject: Staging: hv: storvsc: Get rid of some unnecessary state and definitions Now, get rid of some unnecessary state and definitions. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ce8652e..5e306a5 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -245,7 +245,6 @@ enum storvsc_request_type { struct hv_storvsc_request { - struct hv_storvsc_request *request; struct hv_device *device; /* Synchronize the request/response if needed */ @@ -260,14 +259,6 @@ struct hv_storvsc_request { }; -struct storvsc_device_info { - u32 ring_buffer_size; - unsigned int port_number; - unsigned char path_id; - unsigned char target_id; -}; - - /* A storvsc device is a device object that contains a vmbus channel */ struct storvsc_device { struct hv_device *device; -- cgit v1.1 From cd654ea1cc72aed95e871971d87c4a988924fdda Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:48 -0700 Subject: Staging: hv: storvsc: Eliminate the usage of ext field in struct hv_device Now, eliminate the usage of ext field in struct hv_device for storvsc driver. We do this by registering pointer to struct storvsc_device as the driver specific data and eliminating the current usage of driver specific data to save and retrieve the pointer to struct Scsi_Host. Additionally, all access to the driver specific data is through the vmbus wrapper functions. Note that function to allocate the host gives us a reference on the host object. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 5e306a5..807c94d 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -266,6 +266,7 @@ struct storvsc_device { bool destroy; bool drain_notify; atomic_t num_outstanding_req; + struct Scsi_Host *host; wait_queue_head_t waiting_to_drain; @@ -306,7 +307,7 @@ static inline struct storvsc_device *get_out_stor_device( { struct storvsc_device *stor_device; - stor_device = (struct storvsc_device *)device->ext; + stor_device = hv_get_drvdata(device); if (stor_device && stor_device->destroy) stor_device = NULL; @@ -328,7 +329,7 @@ static inline struct storvsc_device *get_in_stor_device( { struct storvsc_device *stor_device; - stor_device = (struct storvsc_device *)device->ext; + stor_device = hv_get_drvdata(device); if (!stor_device) goto get_in_err; @@ -480,8 +481,7 @@ static void storvsc_on_io_completion(struct hv_device *device, struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; - stor_device = (struct storvsc_device *)device->ext; - + stor_device = hv_get_drvdata(device); stor_pkt = &request->vstor_packet; /* @@ -630,7 +630,7 @@ static int storvsc_dev_remove(struct hv_device *device) struct storvsc_device *stor_device; unsigned long flags; - stor_device = (struct storvsc_device *)device->ext; + stor_device = hv_get_drvdata(device); spin_lock_irqsave(&device->channel->inbound_lock, flags); stor_device->destroy = true; @@ -652,7 +652,7 @@ static int storvsc_dev_remove(struct hv_device *device) * allow incoming packets. */ spin_lock_irqsave(&device->channel->inbound_lock, flags); - device->ext = NULL; + hv_set_drvdata(device, NULL); spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* Close the channel */ @@ -962,7 +962,8 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, static int storvsc_remove(struct hv_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(&dev->device); + struct storvsc_device *stor_device = hv_get_drvdata(dev); + struct Scsi_Host *host = stor_device->host; struct hv_host_device *host_dev = (struct hv_host_device *)host->hostdata; @@ -1338,8 +1339,6 @@ static int storvsc_probe(struct hv_device *device, if (!host) return -ENOMEM; - dev_set_drvdata(&device->device, host); - host_dev = (struct hv_host_device *)host->hostdata; memset(host_dev, 0, sizeof(struct hv_host_device)); @@ -1366,7 +1365,8 @@ static int storvsc_probe(struct hv_device *device, stor_device->destroy = false; init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; - device->ext = stor_device; + stor_device->host = host; + hv_set_drvdata(device, stor_device); stor_device->port_number = host->host_no; ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); -- cgit v1.1 From 2ddd5e5fb342b9f014d61941a4f73c0bd9b50a60 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:49 -0700 Subject: Staging: hv: netvsc: Get rid of the usage of the ext field in struct hv_device Now, eliminate the usage of ext field in struct hv_device for netvsc driver. We do this by registering pointer to struct netvsc_device as the driver specific data and eliminating the current usage of driver specific data to save and retrieve the pointer to struct net_device. Additionally, all access to the driver specific data is through the vmbus wrapper functions. As part of this cleanup, we also get rid of some unnecessary debug print statements. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv_net.h | 2 + drivers/staging/hv/netvsc.c | 86 +++++++++++++++++++-------------------- drivers/staging/hv/netvsc_drv.c | 24 ++++++++--- drivers/staging/hv/rndis_filter.c | 28 +++++++++---- 4 files changed, 83 insertions(+), 57 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index af8a37f..366dd2b 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -392,6 +392,8 @@ struct netvsc_device { struct nvsp_message revoke_packet; /* unsigned char HwMacAddr[HW_MACADDR_LEN]; */ + struct net_device *ndev; + /* Holds rndis device info */ void *extension; }; diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 115629f..2bcc8b2 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -35,6 +35,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) { struct netvsc_device *net_device; + struct net_device *ndev = hv_get_drvdata(device); net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); if (!net_device) @@ -43,8 +44,9 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) net_device->destroy = false; net_device->dev = device; - device->ext = net_device; + net_device->ndev = ndev; + hv_set_drvdata(device, net_device); return net_device; } @@ -52,7 +54,7 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device) { struct netvsc_device *net_device; - net_device = device->ext; + net_device = hv_get_drvdata(device); if (net_device && net_device->destroy) net_device = NULL; @@ -63,7 +65,7 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device) { struct netvsc_device *net_device; - net_device = device->ext; + net_device = hv_get_drvdata(device); if (!net_device) goto get_in_err; @@ -81,7 +83,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) { struct nvsp_message *revoke_packet; int ret = 0; - struct net_device *ndev = dev_get_drvdata(&net_device->dev->device); + struct net_device *ndev = net_device->ndev; /* * If we got a section count, it means we received a @@ -153,14 +155,12 @@ static int netvsc_init_recv_buf(struct hv_device *device) int t; struct netvsc_device *net_device; struct nvsp_message *init_packet; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; net_device = get_outbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "unable to get net device..." - "device being destroyed?\n"); + if (!net_device) return -ENODEV; - } + ndev = net_device->ndev; net_device->recv_buf = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, @@ -269,14 +269,12 @@ static int netvsc_connect_vsp(struct hv_device *device) struct netvsc_device *net_device; struct nvsp_message *init_packet; int ndis_version; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; net_device = get_outbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "unable to get net device..." - "device being destroyed?\n"); + if (!net_device) return -ENODEV; - } + ndev = net_device->ndev; init_packet = &net_device->channel_init_pkt; @@ -357,7 +355,7 @@ int netvsc_device_remove(struct hv_device *device) struct hv_netvsc_packet *netvsc_packet, *pos; unsigned long flags; - net_device = (struct netvsc_device *)device->ext; + net_device = hv_get_drvdata(device); spin_lock_irqsave(&device->channel->inbound_lock, flags); net_device->destroy = true; spin_unlock_irqrestore(&device->channel->inbound_lock, flags); @@ -381,7 +379,7 @@ int netvsc_device_remove(struct hv_device *device) */ spin_lock_irqsave(&device->channel->inbound_lock, flags); - device->ext = NULL; + hv_set_drvdata(device, NULL); spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* At this point, no one should be accessing netDevice except in here */ @@ -407,14 +405,12 @@ static void netvsc_send_completion(struct hv_device *device, struct netvsc_device *net_device; struct nvsp_message *nvsp_packet; struct hv_netvsc_packet *nvsc_packet; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; net_device = get_inbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "unable to get net device..." - "device being destroyed?\n"); + if (!net_device) return; - } + ndev = net_device->ndev; nvsp_packet = (struct nvsp_message *)((unsigned long)packet + (packet->offset8 << 3)); @@ -452,14 +448,12 @@ int netvsc_send(struct hv_device *device, struct netvsc_device *net_device; int ret = 0; struct nvsp_message sendMessage; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; net_device = get_outbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "net device (%p) shutting down..." - "ignoring outbound packets\n", net_device); + if (!net_device) return -ENODEV; - } + ndev = net_device->ndev; sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; if (packet->is_data_pkt) { @@ -506,7 +500,10 @@ static void netvsc_send_recv_completion(struct hv_device *device, struct nvsp_message recvcompMessage; int retries = 0; int ret; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; + struct netvsc_device *net_device = hv_get_drvdata(device); + + ndev = net_device->ndev; recvcompMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; @@ -552,7 +549,7 @@ static void netvsc_receive_completion(void *context) u64 transaction_id = 0; bool fsend_receive_comp = false; unsigned long flags; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; /* * Even though it seems logical to do a GetOutboundNetDevice() here to @@ -560,11 +557,9 @@ static void netvsc_receive_completion(void *context) * since we may have disable outbound traffic already. */ net_device = get_inbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "unable to get net device..." - "device being destroyed?\n"); + if (!net_device) return; - } + ndev = net_device->ndev; /* Overloading use of the lock. */ spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); @@ -607,16 +602,14 @@ static void netvsc_receive(struct hv_device *device, int i, j; int count = 0, bytes_remain = 0; unsigned long flags; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; LIST_HEAD(listHead); net_device = get_inbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "unable to get net device..." - "device being destroyed?\n"); + if (!net_device) return; - } + ndev = net_device->ndev; /* * All inbound packets other than send completion should be xfer page @@ -784,7 +777,7 @@ static void netvsc_channel_cb(void *context) struct vmpacket_descriptor *desc; unsigned char *buffer; int bufferlen = NETVSC_PACKET_SIZE; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), GFP_ATOMIC); @@ -793,11 +786,9 @@ static void netvsc_channel_cb(void *context) buffer = packet; net_device = get_inbound_net_device(device); - if (!net_device) { - netdev_err(ndev, "net device (%p) shutting down..." - "ignoring inbound packets\n", net_device); + if (!net_device) goto out; - } + ndev = net_device->ndev; do { ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, @@ -871,7 +862,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) ((struct netvsc_device_info *)additional_info)->ring_size; struct netvsc_device *net_device; struct hv_netvsc_packet *packet, *pos; - struct net_device *ndev = dev_get_drvdata(&device->device); + struct net_device *ndev; net_device = alloc_net_device(device); if (!net_device) { @@ -879,6 +870,15 @@ int netvsc_device_add(struct hv_device *device, void *additional_info) goto cleanup; } + /* + * Coming into this function, struct net_device * is + * registered as the driver private data. + * In alloc_net_device(), we register struct netvsc_device * + * as the driver private data and stash away struct net_device * + * in struct netvsc_device *. + */ + ndev = net_device->ndev; + /* Initialize the NetVSC channel extension */ net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; spin_lock_init(&net_device->recv_pkt_list_lock); diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index d06cde29..69c233e 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -203,8 +203,12 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status) { - struct net_device *net = dev_get_drvdata(&device_obj->device); + struct net_device *net; struct net_device_context *ndev_ctx; + struct netvsc_device *net_device; + + net_device = hv_get_drvdata(device_obj); + net = net_device->ndev; if (!net) { netdev_err(net, "got link status but net device " @@ -236,6 +240,10 @@ int netvsc_recv_callback(struct hv_device *device_obj, void *data; int i; unsigned long flags; + struct netvsc_device *net_device; + + net_device = hv_get_drvdata(device_obj); + net = net_device->ndev; if (!net) { netdev_err(net, "got receive callback but net device" @@ -322,9 +330,11 @@ static void netvsc_send_garp(struct work_struct *w) { struct net_device_context *ndev_ctx; struct net_device *net; + struct netvsc_device *net_device; ndev_ctx = container_of(w, struct net_device_context, dwork.work); - net = dev_get_drvdata(&ndev_ctx->device_ctx->device); + net_device = hv_get_drvdata(ndev_ctx->device_ctx); + net = net_device->ndev; netif_notify_peers(net); } @@ -347,7 +357,7 @@ static int netvsc_probe(struct hv_device *dev, net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; atomic_set(&net_device_ctx->avail, ring_size); - dev_set_drvdata(&dev->device, net); + hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); net->netdev_ops = &device_ops; @@ -373,7 +383,7 @@ static int netvsc_probe(struct hv_device *dev, netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); unregister_netdev(net); free_netdev(net); - dev_set_drvdata(&dev->device, NULL); + hv_set_drvdata(dev, NULL); return ret; } memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); @@ -386,8 +396,12 @@ out: static int netvsc_remove(struct hv_device *dev) { - struct net_device *net = dev_get_drvdata(&dev->device); + struct net_device *net; struct net_device_context *ndev_ctx; + struct netvsc_device *net_device; + + net_device = hv_get_drvdata(dev); + net = net_device->ndev; if (net == NULL) { dev_err(&dev->device, "No net device to remove\n"); diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index b325345..b354b0b 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -141,7 +141,11 @@ static void put_rndis_request(struct rndis_device *dev, static void dump_rndis_message(struct hv_device *hv_dev, struct rndis_message *rndis_msg) { - struct net_device *netdev = dev_get_drvdata(&hv_dev->device); + struct net_device *netdev; + struct netvsc_device *net_device; + + net_device = hv_get_drvdata(hv_dev); + netdev = net_device->ndev; switch (rndis_msg->ndis_msg_type) { case REMOTE_NDIS_PACKET_MSG: @@ -249,7 +253,9 @@ static void rndis_filter_receive_response(struct rndis_device *dev, struct rndis_request *request = NULL; bool found = false; unsigned long flags; - struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device); + struct net_device *ndev; + + ndev = dev->net_dev->ndev; spin_lock_irqsave(&dev->request_lock, flags); list_for_each_entry(request, &dev->req_list, list_ent) { @@ -356,11 +362,13 @@ static void rndis_filter_receive_data(struct rndis_device *dev, int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt) { - struct netvsc_device *net_dev = dev->ext; + struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev; struct rndis_message rndis_msg; struct rndis_message *rndis_hdr; - struct net_device *ndev = dev_get_drvdata(&dev->device); + struct net_device *ndev; + + ndev = net_dev->ndev; if (!net_dev) return -EINVAL; @@ -517,7 +525,9 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, struct rndis_set_complete *set_complete; u32 status; int ret, t; - struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device); + struct net_device *ndev; + + ndev = dev->net_dev->ndev; request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + @@ -700,7 +710,7 @@ int rndis_filter_device_add(struct hv_device *dev, /* Initialize the rndis device */ - netDevice = dev->ext; + netDevice = hv_get_drvdata(dev); netDevice->extension = rndisDevice; rndisDevice->net_dev = netDevice; @@ -737,7 +747,7 @@ int rndis_filter_device_add(struct hv_device *dev, void rndis_filter_device_remove(struct hv_device *dev) { - struct netvsc_device *net_dev = dev->ext; + struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev = net_dev->extension; /* Halt and release the rndis device */ @@ -752,7 +762,7 @@ void rndis_filter_device_remove(struct hv_device *dev) int rndis_filter_open(struct hv_device *dev) { - struct netvsc_device *netDevice = dev->ext; + struct netvsc_device *netDevice = hv_get_drvdata(dev); if (!netDevice) return -EINVAL; @@ -762,7 +772,7 @@ int rndis_filter_open(struct hv_device *dev) int rndis_filter_close(struct hv_device *dev) { - struct netvsc_device *netDevice = dev->ext; + struct netvsc_device *netDevice = hv_get_drvdata(dev); if (!netDevice) return -EINVAL; -- cgit v1.1 From 80e623887ef6a86718ecab257c592e214ecad82d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:50 -0700 Subject: Staging: hv: mousevsc: Get rid of the usage of the ext field in struct hv_device Get rid of the usage of the ext field in struct hv_device for the mouse driver. We do this by using the newly introduced functions to set and and get driver specific data. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 5ff8a03..fcb023a 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -196,7 +196,7 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) atomic_cmpxchg(&input_dev->ref_count, 0, 2); input_dev->device = device; - device->ext = input_dev; + hv_set_drvdata(device, input_dev); return input_dev; } @@ -214,7 +214,7 @@ static struct mousevsc_dev *get_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* * FIXME @@ -240,7 +240,7 @@ static struct mousevsc_dev *must_get_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); if (input_dev && atomic_read(&input_dev->ref_count)) atomic_inc(&input_dev->ref_count); @@ -254,7 +254,7 @@ static void put_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); atomic_dec(&input_dev->ref_count); } @@ -266,7 +266,7 @@ static struct mousevsc_dev *release_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* Busy wait until the ref drop to 2, then set it to 1 */ while (atomic_cmpxchg(&input_dev->ref_count, 2, 1) != 2) @@ -282,13 +282,13 @@ static struct mousevsc_dev *final_release_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* Busy wait until the ref drop to 1, then set it to 0 */ while (atomic_cmpxchg(&input_dev->ref_count, 1, 0) != 1) udelay(100); - device->ext = NULL; + hv_set_drvdata(device, NULL); return input_dev; } @@ -790,7 +790,7 @@ static int mousevsc_on_device_remove(struct hv_device *device) int ret = 0; pr_info("disabling input device (%p)...", - device->ext); + hv_get_drvdata(device)); input_dev = release_input_device(device); @@ -808,7 +808,7 @@ static int mousevsc_on_device_remove(struct hv_device *device) udelay(100); } - pr_info("removing input device (%p)...", device->ext); + pr_info("removing input device (%p)...", hv_get_drvdata(device)); input_dev = final_release_input_device(device); -- cgit v1.1 From b0bb55175f846909e06952583e38982a77f7ecea Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:51 -0700 Subject: Staging: hv: vmbus: Get rid of the ext field in struct hv_device Now that we have eliminated all uses of the ext field in struct hv_device, get rid of the ext field. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hyperv.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index 91e557b..76e2ddd 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -827,9 +827,6 @@ struct hv_device { struct device device; struct vmbus_channel *channel; - - /* Device extension; */ - void *ext; }; -- cgit v1.1 From 7bb52384b2678fcbcebfa97be8f98dfb3219edc1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:52 -0700 Subject: Staging: hv: vmbus: Do not allocate struct hv_device_info on the stack struct hv_device_info is about 101 bytes in size. Do not allocate this structure on the stack. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 134 +++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 65 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 466425a..d2562af 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -112,101 +112,105 @@ static ssize_t vmbus_show_device_attr(struct device *dev, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); - struct hv_device_info device_info; + struct hv_device_info *device_info; char alias_name[VMBUS_ALIAS_LEN + 1]; + int ret = 0; - memset(&device_info, 0, sizeof(struct hv_device_info)); + device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL); + if (!device_info) + return ret; - get_channel_info(hv_dev, &device_info); + get_channel_info(hv_dev, device_info); if (!strcmp(dev_attr->attr.name, "class_id")) { - return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" + ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info.chn_type.b[3], - device_info.chn_type.b[2], - device_info.chn_type.b[1], - device_info.chn_type.b[0], - device_info.chn_type.b[5], - device_info.chn_type.b[4], - device_info.chn_type.b[7], - device_info.chn_type.b[6], - device_info.chn_type.b[8], - device_info.chn_type.b[9], - device_info.chn_type.b[10], - device_info.chn_type.b[11], - device_info.chn_type.b[12], - device_info.chn_type.b[13], - device_info.chn_type.b[14], - device_info.chn_type.b[15]); + device_info->chn_type.b[3], + device_info->chn_type.b[2], + device_info->chn_type.b[1], + device_info->chn_type.b[0], + device_info->chn_type.b[5], + device_info->chn_type.b[4], + device_info->chn_type.b[7], + device_info->chn_type.b[6], + device_info->chn_type.b[8], + device_info->chn_type.b[9], + device_info->chn_type.b[10], + device_info->chn_type.b[11], + device_info->chn_type.b[12], + device_info->chn_type.b[13], + device_info->chn_type.b[14], + device_info->chn_type.b[15]); } else if (!strcmp(dev_attr->attr.name, "device_id")) { - return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" + ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info.chn_instance.b[3], - device_info.chn_instance.b[2], - device_info.chn_instance.b[1], - device_info.chn_instance.b[0], - device_info.chn_instance.b[5], - device_info.chn_instance.b[4], - device_info.chn_instance.b[7], - device_info.chn_instance.b[6], - device_info.chn_instance.b[8], - device_info.chn_instance.b[9], - device_info.chn_instance.b[10], - device_info.chn_instance.b[11], - device_info.chn_instance.b[12], - device_info.chn_instance.b[13], - device_info.chn_instance.b[14], - device_info.chn_instance.b[15]); + device_info->chn_instance.b[3], + device_info->chn_instance.b[2], + device_info->chn_instance.b[1], + device_info->chn_instance.b[0], + device_info->chn_instance.b[5], + device_info->chn_instance.b[4], + device_info->chn_instance.b[7], + device_info->chn_instance.b[6], + device_info->chn_instance.b[8], + device_info->chn_instance.b[9], + device_info->chn_instance.b[10], + device_info->chn_instance.b[11], + device_info->chn_instance.b[12], + device_info->chn_instance.b[13], + device_info->chn_instance.b[14], + device_info->chn_instance.b[15]); } else if (!strcmp(dev_attr->attr.name, "modalias")) { print_alias_name(hv_dev, alias_name); - return sprintf(buf, "vmbus:%s\n", alias_name); + ret = sprintf(buf, "vmbus:%s\n", alias_name); } else if (!strcmp(dev_attr->attr.name, "state")) { - return sprintf(buf, "%d\n", device_info.chn_state); + ret = sprintf(buf, "%d\n", device_info->chn_state); } else if (!strcmp(dev_attr->attr.name, "id")) { - return sprintf(buf, "%d\n", device_info.chn_id); + ret = sprintf(buf, "%d\n", device_info->chn_id); } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { - return sprintf(buf, "%d\n", device_info.outbound.int_mask); + ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { - return sprintf(buf, "%d\n", device_info.outbound.read_idx); + ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { - return sprintf(buf, "%d\n", device_info.outbound.write_idx); + ret = sprintf(buf, "%d\n", device_info->outbound.write_idx); } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { - return sprintf(buf, "%d\n", - device_info.outbound.bytes_avail_toread); + ret = sprintf(buf, "%d\n", + device_info->outbound.bytes_avail_toread); } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) { - return sprintf(buf, "%d\n", - device_info.outbound.bytes_avail_towrite); + ret = sprintf(buf, "%d\n", + device_info->outbound.bytes_avail_towrite); } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { - return sprintf(buf, "%d\n", device_info.inbound.int_mask); + ret = sprintf(buf, "%d\n", device_info->inbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { - return sprintf(buf, "%d\n", device_info.inbound.read_idx); + ret = sprintf(buf, "%d\n", device_info->inbound.read_idx); } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { - return sprintf(buf, "%d\n", device_info.inbound.write_idx); + ret = sprintf(buf, "%d\n", device_info->inbound.write_idx); } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { - return sprintf(buf, "%d\n", - device_info.inbound.bytes_avail_toread); + ret = sprintf(buf, "%d\n", + device_info->inbound.bytes_avail_toread); } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { - return sprintf(buf, "%d\n", - device_info.inbound.bytes_avail_towrite); + ret = sprintf(buf, "%d\n", + device_info->inbound.bytes_avail_towrite); } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { - return sprintf(buf, "%d\n", device_info.monitor_id); + ret = sprintf(buf, "%d\n", device_info->monitor_id); } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { - return sprintf(buf, "%d\n", device_info.server_monitor_pending); + ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { - return sprintf(buf, "%d\n", device_info.server_monitor_latency); + ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { - return sprintf(buf, "%d\n", - device_info.server_monitor_conn_id); + ret = sprintf(buf, "%d\n", + device_info->server_monitor_conn_id); } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { - return sprintf(buf, "%d\n", device_info.client_monitor_pending); + ret = sprintf(buf, "%d\n", device_info->client_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { - return sprintf(buf, "%d\n", device_info.client_monitor_latency); + ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { - return sprintf(buf, "%d\n", - device_info.client_monitor_conn_id); - } else { - return 0; + ret = sprintf(buf, "%d\n", + device_info->client_monitor_conn_id); } + + kfree(device_info); + return ret; } /* Set up per device attributes in /sys/bus/vmbus/devices/ */ -- cgit v1.1 From d982042b9b62f3a966e7de5572fd30d131eb5357 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:53 -0700 Subject: Staging: hv: vmbus: Get rid of the module dependency Hyper-V modules can be built as part of the kernel (not just as modules). Get rid of the module dependency in Kconfig. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig index 26b5064..815f8c2 100644 --- a/drivers/staging/hv/Kconfig +++ b/drivers/staging/hv/Kconfig @@ -1,6 +1,6 @@ config HYPERV tristate "Microsoft Hyper-V client drivers" - depends on X86 && ACPI && PCI && m + depends on X86 && ACPI && PCI default n help Select this option to run Linux as a Hyper-V client operating -- cgit v1.1 From 86c921af41f0d40ff9105a73fb20378440f0299f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:54 -0700 Subject: Staging: hv: netvsc: Rename netDevice as net_device Rename netDevice as net_device. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc.c | 5 ++++- drivers/staging/hv/rndis_filter.c | 14 +++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 2bcc8b2..b902579 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -382,7 +382,10 @@ int netvsc_device_remove(struct hv_device *device) hv_set_drvdata(device, NULL); spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - /* At this point, no one should be accessing netDevice except in here */ + /* + * At this point, no one should be accessing net_device + * except in here + */ dev_notice(&device->device, "net device safe to remove\n"); /* Now, we can close the channel safely */ diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index b354b0b..efa7df5 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -689,7 +689,7 @@ int rndis_filter_device_add(struct hv_device *dev, void *additional_info) { int ret; - struct netvsc_device *netDevice; + struct netvsc_device *net_device; struct rndis_device *rndisDevice; struct netvsc_device_info *deviceInfo = additional_info; @@ -710,10 +710,10 @@ int rndis_filter_device_add(struct hv_device *dev, /* Initialize the rndis device */ - netDevice = hv_get_drvdata(dev); + net_device = hv_get_drvdata(dev); - netDevice->extension = rndisDevice; - rndisDevice->net_dev = netDevice; + net_device->extension = rndisDevice; + rndisDevice->net_dev = net_device; /* Send the rndis initialization message */ ret = rndis_filter_init_device(rndisDevice); @@ -762,12 +762,12 @@ void rndis_filter_device_remove(struct hv_device *dev) int rndis_filter_open(struct hv_device *dev) { - struct netvsc_device *netDevice = hv_get_drvdata(dev); + struct netvsc_device *net_device = hv_get_drvdata(dev); - if (!netDevice) + if (!net_device) return -EINVAL; - return rndis_filter_open_device(netDevice->extension); + return rndis_filter_open_device(net_device->extension); } int rndis_filter_close(struct hv_device *dev) -- cgit v1.1 From b13cc345b6f7aae293050c33e86f585ea30b2e38 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:55 -0700 Subject: Staging: hv: netvsc: Rename rndisDevice to rndis_device Rename rndisDevice to rndis_device. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index efa7df5..bfe9129 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -690,11 +690,11 @@ int rndis_filter_device_add(struct hv_device *dev, { int ret; struct netvsc_device *net_device; - struct rndis_device *rndisDevice; + struct rndis_device *rndis_device; struct netvsc_device_info *deviceInfo = additional_info; - rndisDevice = get_rndis_device(); - if (!rndisDevice) + rndis_device = get_rndis_device(); + if (!rndis_device) return -ENODEV; /* @@ -704,7 +704,7 @@ int rndis_filter_device_add(struct hv_device *dev, */ ret = netvsc_device_add(dev, additional_info); if (ret != 0) { - kfree(rndisDevice); + kfree(rndis_device); return ret; } @@ -712,11 +712,11 @@ int rndis_filter_device_add(struct hv_device *dev, /* Initialize the rndis device */ net_device = hv_get_drvdata(dev); - net_device->extension = rndisDevice; - rndisDevice->net_dev = net_device; + net_device->extension = rndis_device; + rndis_device->net_dev = net_device; /* Send the rndis initialization message */ - ret = rndis_filter_init_device(rndisDevice); + ret = rndis_filter_init_device(rndis_device); if (ret != 0) { /* * TODO: If rndis init failed, we will need to shut down the @@ -725,21 +725,21 @@ int rndis_filter_device_add(struct hv_device *dev, } /* Get the mac address */ - ret = rndis_filter_query_device_mac(rndisDevice); + ret = rndis_filter_query_device_mac(rndis_device); if (ret != 0) { /* * TODO: shutdown rndis device and the channel */ } - memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN); + memcpy(deviceInfo->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); - rndis_filter_query_device_link_status(rndisDevice); + rndis_filter_query_device_link_status(rndis_device); - deviceInfo->link_state = rndisDevice->link_stat; + deviceInfo->link_state = rndis_device->link_stat; dev_info(&dev->device, "Device MAC %pM link state %s", - rndisDevice->hw_mac_adr, + rndis_device->hw_mac_adr, ((deviceInfo->link_state) ? ("down\n") : ("up\n"))); return ret; -- cgit v1.1 From 3c4debad4290a31d3537bf89837f49d5e48b8271 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 10:59:56 -0700 Subject: Staging: hv: netvsc: Rename deviceInfo as device_info Rename deviceInfo as device_info. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index bfe9129..963582a 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -691,7 +691,7 @@ int rndis_filter_device_add(struct hv_device *dev, int ret; struct netvsc_device *net_device; struct rndis_device *rndis_device; - struct netvsc_device_info *deviceInfo = additional_info; + struct netvsc_device_info *device_info = additional_info; rndis_device = get_rndis_device(); if (!rndis_device) @@ -732,15 +732,15 @@ int rndis_filter_device_add(struct hv_device *dev, */ } - memcpy(deviceInfo->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); + memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); rndis_filter_query_device_link_status(rndis_device); - deviceInfo->link_state = rndis_device->link_stat; + device_info->link_state = rndis_device->link_stat; dev_info(&dev->device, "Device MAC %pM link state %s", rndis_device->hw_mac_adr, - ((deviceInfo->link_state) ? ("down\n") : ("up\n"))); + ((device_info->link_state) ? ("down\n") : ("up\n"))); return ret; } -- cgit v1.1 From 6f27457b50c0439388e34d528f0fc200ddedb9a4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 13 Sep 2011 15:21:27 -0700 Subject: Staging: hv: netvsc: Cleanup the name and type of link_stat variable Consistently name the variable tracking the link status. Use a consistent type for this variable and get rid of some unnecessary parentheses as well. I would like to thank Joe Perches for suggesting these changes and patiently helping me get here! Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index 963582a..ef43f2e 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -41,7 +41,7 @@ struct rndis_device { struct netvsc_device *net_dev; enum rndis_device_state state; - u32 link_stat; + bool link_state; atomic_t new_req_id; spinlock_t request_lock; @@ -511,10 +511,15 @@ static int rndis_filter_query_device_mac(struct rndis_device *dev) static int rndis_filter_query_device_link_status(struct rndis_device *dev) { u32 size = sizeof(u32); + u32 link_status; + int ret; - return rndis_filter_query_device(dev, + ret = rndis_filter_query_device(dev, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, - &dev->link_stat, &size); + &link_status, &size); + dev->link_state = (link_status != 0) ? true : false; + + return ret; } static int rndis_filter_set_packet_filter(struct rndis_device *dev, @@ -736,11 +741,11 @@ int rndis_filter_device_add(struct hv_device *dev, rndis_filter_query_device_link_status(rndis_device); - device_info->link_state = rndis_device->link_stat; + device_info->link_state = rndis_device->link_state; - dev_info(&dev->device, "Device MAC %pM link state %s", + dev_info(&dev->device, "Device MAC %pM link state %s\n", rndis_device->hw_mac_adr, - ((device_info->link_state) ? ("down\n") : ("up\n"))); + device_info->link_state ? "down" : "up"); return ret; } -- cgit v1.1 From a29b643c5767558956450b86d79eb66334704ac2 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 18 Sep 2011 10:31:33 -0700 Subject: Staging: hv: util: Perform some service specific init/deinit in probe/remove In preparation for modifying the util driver to fully conform to the Linux Driver Model, perform some service specific init and de-init operations in util_probe()/util_remove() as opposed to in init_hyperv_utils()/exit_hyperv_utils() as is currently done. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_kvp.c | 7 +--- drivers/staging/hv/hv_kvp.h | 2 +- drivers/staging/hv/hv_util.c | 91 ++++++++++++++++++++++++++------------------ drivers/staging/hv/hyperv.h | 13 +++++++ 4 files changed, 71 insertions(+), 42 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index 13b0ecf..ff0d9ab 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c @@ -312,16 +312,14 @@ callback_done: } int -hv_kvp_init(void) +hv_kvp_init(struct hv_util_service *srv) { int err; err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback); if (err) return err; - recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!recv_buffer) - return -ENOMEM; + recv_buffer = srv->recv_buffer; return 0; } @@ -330,5 +328,4 @@ void hv_kvp_deinit(void) { cn_del_callback(&kvp_id); cancel_delayed_work_sync(&kvp_work); - kfree(recv_buffer); } diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h index 8c402f3..9b765d7 100644 --- a/drivers/staging/hv/hv_kvp.h +++ b/drivers/staging/hv/hv_kvp.h @@ -175,7 +175,7 @@ struct hv_kvp_msg { struct hv_kvp_msg_enumerate kvp_data; }; -int hv_kvp_init(void); +int hv_kvp_init(struct hv_util_service *); void hv_kvp_deinit(void); void hv_kvp_onchannelcallback(void *); diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index d9460fdd..a1539a7 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -30,9 +30,27 @@ #include "hyperv.h" #include "hv_kvp.h" -static u8 *shut_txf_buf; -static u8 *time_txf_buf; -static u8 *hbeat_txf_buf; + +static void shutdown_onchannelcallback(void *context); +static struct hv_util_service util_shutdown = { + .util_cb = shutdown_onchannelcallback, +}; + +static void timesync_onchannelcallback(void *context); +static struct hv_util_service util_timesynch = { + .util_cb = timesync_onchannelcallback, +}; + +static void heartbeat_onchannelcallback(void *context); +static struct hv_util_service util_heartbeat = { + .util_cb = heartbeat_onchannelcallback, +}; + +static struct hv_util_service util_kvp = { + .util_cb = hv_kvp_onchannelcallback, + .util_init = hv_kvp_init, + .util_deinit = hv_kvp_deinit, +}; static void shutdown_onchannelcallback(void *context) { @@ -40,6 +58,7 @@ static void shutdown_onchannelcallback(void *context) u32 recvlen; u64 requestid; u8 execute_shutdown = false; + u8 *shut_txf_buf = util_shutdown.recv_buffer; struct shutdown_msg_data *shutdown_msg; @@ -169,6 +188,7 @@ static void timesync_onchannelcallback(void *context) u64 requestid; struct icmsg_hdr *icmsghdrp; struct ictimesync_data *timedatap; + u8 *time_txf_buf = util_timesynch.recv_buffer; vmbus_recvpacket(channel, time_txf_buf, PAGE_SIZE, &recvlen, &requestid); @@ -207,6 +227,7 @@ static void heartbeat_onchannelcallback(void *context) u64 requestid; struct icmsg_hdr *icmsghdrp; struct heartbeat_msg_data *heartbeat_msg; + u8 *hbeat_txf_buf = util_heartbeat.recv_buffer; vmbus_recvpacket(channel, hbeat_txf_buf, PAGE_SIZE, &recvlen, &requestid); @@ -235,34 +256,56 @@ static void heartbeat_onchannelcallback(void *context) } } -/* - * The devices managed by the util driver don't need any additional - * setup. - */ static int util_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { + struct hv_util_service *srv = + (struct hv_util_service *)dev_id->driver_data; + int ret; + + srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!srv->recv_buffer) + return -ENOMEM; + if (srv->util_init) { + ret = srv->util_init(srv); + if (ret) { + kfree(srv->recv_buffer); + return -ENODEV; + } + } + + hv_set_drvdata(dev, srv); return 0; } static int util_remove(struct hv_device *dev) { + struct hv_util_service *srv = hv_get_drvdata(dev); + + if (srv->util_deinit) + srv->util_deinit(); + kfree(srv->recv_buffer); + return 0; } static const struct hv_vmbus_device_id id_table[] = { /* Shutdown guid */ { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) }, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) + .driver_data = (unsigned long)&util_shutdown }, /* Time synch guid */ { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) }, + 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) + .driver_data = (unsigned long)&util_timesynch }, /* Heartbeat guid */ { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) }, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) + .driver_data = (unsigned long)&util_heartbeat }, /* KVP guid */ { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) }, + 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) + .driver_data = (unsigned long)&util_kvp }, { }, }; @@ -281,24 +324,11 @@ static int __init init_hyperv_utils(void) int ret; pr_info("Registering HyperV Utility Driver\n"); - if (hv_kvp_init()) - return -ENODEV; - - - shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - - if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) { - pr_info("Unable to allocate memory for receive buffer\n"); - ret = -ENOMEM; - goto err; - } ret = vmbus_driver_register(&util_drv); if (ret != 0) - goto err; + return ret; hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; @@ -310,12 +340,6 @@ static int __init init_hyperv_utils(void) return 0; -err: - kfree(shut_txf_buf); - kfree(time_txf_buf); - kfree(hbeat_txf_buf); - - return ret; } static void exit_hyperv_utils(void) @@ -342,11 +366,6 @@ static void exit_hyperv_utils(void) &chn_cb_negotiate; hv_cb_utils[HV_KVP_MSG].callback = NULL; - hv_kvp_deinit(); - - kfree(shut_txf_buf); - kfree(time_txf_buf); - kfree(hbeat_txf_buf); vmbus_driver_unregister(&util_drv); } diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index 76e2ddd..5c3e297 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -889,6 +889,19 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver); #define HV_ERROR_NOT_SUPPORTED 0x80070032 #define HV_ERROR_MACHINE_LOCKED 0x800704F7 +/* + * While we want to handle util services as regular devices, + * there is only one instance of each of these services; so + * we statically allocate the service specific state. + */ + +struct hv_util_service { + u8 *recv_buffer; + void (*util_cb)(void *); + int (*util_init)(struct hv_util_service *); + void (*util_deinit)(void); +}; + struct vmbuspipe_hdr { u32 flags; u32 msgsize; -- cgit v1.1 From 4e65f6e80593c316c5a65a71191fa480360f165d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 18 Sep 2011 10:31:34 -0700 Subject: Staging: hv: util: Properly handle util services in the util driver Now, properly handle util services in the util driver and eliminate code that will not be necessary. In the current code, util services were all handled not as other vmbus devices (net, block) but rather through special handling (channel setup etc.). In this patch we handle all services using the standard Linux Driver Model. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 36 ------------------------- drivers/staging/hv/hv_kvp.c | 7 +++++ drivers/staging/hv/hv_util.c | 55 ++++++++++++--------------------------- 3 files changed, 23 insertions(+), 75 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index c68e5fa..99cc334 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -181,24 +181,6 @@ void chn_cb_negotiate(void *context) struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; - if (channel->util_index >= 0) { - /* - * This is a properly initialized util channel. - * Route this callback appropriately and setup state - * so that we don't need to reroute again. - */ - if (hv_cb_utils[channel->util_index].callback != NULL) { - /* - * The util driver has established a handler for - * this service; do the magic. - */ - channel->onchannel_callback = - hv_cb_utils[channel->util_index].callback; - (hv_cb_utils[channel->util_index].callback)(channel); - return; - } - } - buflen = PAGE_SIZE; buf = kmalloc(buflen, GFP_ATOMIC); @@ -348,7 +330,6 @@ static void vmbus_process_offer(struct work_struct *work) struct vmbus_channel *channel; bool fnew = true; int ret; - int cnt; unsigned long flags; /* The next possible work is rescind handling */ @@ -410,23 +391,6 @@ static void vmbus_process_offer(struct work_struct *work) * can cleanup properly */ newchannel->state = CHANNEL_OPEN_STATE; - newchannel->util_index = -1; /* Invalid index */ - - /* Open IC channels */ - for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) { - if (!uuid_le_cmp(newchannel->offermsg.offer.if_type, - hv_cb_utils[cnt].data) && - vmbus_open(newchannel, 2 * PAGE_SIZE, - 2 * PAGE_SIZE, NULL, 0, - chn_cb_negotiate, - newchannel) == 0) { - hv_cb_utils[cnt].channel = newchannel; - newchannel->util_index = cnt; - - pr_info("%s\n", hv_cb_utils[cnt].log_msg); - - } - } } } diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index ff0d9ab..9aa9ede 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c @@ -177,6 +177,13 @@ kvp_respond_to_host(char *key, char *value, int error) channel = kvp_transaction.recv_channel; req_id = kvp_transaction.recv_req_id; + if (channel->onchannel_callback == NULL) + /* + * We have raced with util driver being unloaded; + * silently return. + */ + return; + icmsghdrp = (struct icmsg_hdr *) &recv_buffer[sizeof(struct vmbuspipe_hdr)]; kvp_msg = (struct hv_kvp_msg *) diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index a1539a7..faa6607 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -269,19 +269,32 @@ static int util_probe(struct hv_device *dev, if (srv->util_init) { ret = srv->util_init(srv); if (ret) { - kfree(srv->recv_buffer); - return -ENODEV; + ret = -ENODEV; + goto error1; } } + ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, + srv->util_cb, dev->channel); + if (ret) + goto error; + hv_set_drvdata(dev, srv); return 0; + +error: + if (srv->util_deinit) + srv->util_deinit(); +error1: + kfree(srv->recv_buffer); + return ret; } static int util_remove(struct hv_device *dev) { struct hv_util_service *srv = hv_get_drvdata(dev); + vmbus_close(dev->channel); if (srv->util_deinit) srv->util_deinit(); kfree(srv->recv_buffer); @@ -321,51 +334,15 @@ static struct hv_driver util_drv = { static int __init init_hyperv_utils(void) { - int ret; pr_info("Registering HyperV Utility Driver\n"); - - ret = vmbus_driver_register(&util_drv); - - if (ret != 0) - return ret; - - hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; - - hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback; - - hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback; - - hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; - - return 0; - + return vmbus_driver_register(&util_drv); } static void exit_hyperv_utils(void) { pr_info("De-Registered HyperV Utility Driver\n"); - if (hv_cb_utils[HV_SHUTDOWN_MSG].channel != NULL) - hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback = - &chn_cb_negotiate; - hv_cb_utils[HV_SHUTDOWN_MSG].callback = NULL; - - if (hv_cb_utils[HV_TIMESYNC_MSG].channel != NULL) - hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback = - &chn_cb_negotiate; - hv_cb_utils[HV_TIMESYNC_MSG].callback = NULL; - - if (hv_cb_utils[HV_HEARTBEAT_MSG].channel != NULL) - hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback = - &chn_cb_negotiate; - hv_cb_utils[HV_HEARTBEAT_MSG].callback = NULL; - - if (hv_cb_utils[HV_KVP_MSG].channel != NULL) - hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback = - &chn_cb_negotiate; - hv_cb_utils[HV_KVP_MSG].callback = NULL; - vmbus_driver_unregister(&util_drv); } -- cgit v1.1 From e0f4c6742bdbb2792bd67b147af9c1fd9176b94a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 18 Sep 2011 10:31:35 -0700 Subject: Staging: hv: vmbus: Get rid of hv_cb_utils[] and other unneeded code Now that the transformation of the util driver is complete, get rid of hv_cb_utils[] and other unneeded code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/channel_mgmt.c | 94 --------------------------------------- drivers/staging/hv/hyperv.h | 13 ------ 2 files changed, 107 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 99cc334..9f00752 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -158,100 +158,6 @@ void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, } EXPORT_SYMBOL(prep_negotiate_resp); -/** - * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK - * Hyper-V requests - * @context: Pointer to argument structure. - * - * Set up the default handler for non device driver specific requests - * from Hyper-V. This stub responds to the default negotiate messages - * that come in for every non IDE/SCSI/Network request. - * This behavior is normally overwritten in the hv_utils driver. That - * driver handles requests like graceful shutdown, heartbeats etc. - * - * Mainly used by Hyper-V drivers. - */ -void chn_cb_negotiate(void *context) -{ - struct vmbus_channel *channel = context; - u8 *buf; - u32 buflen, recvlen; - u64 requestid; - - struct icmsg_hdr *icmsghdrp; - struct icmsg_negotiate *negop = NULL; - - buflen = PAGE_SIZE; - buf = kmalloc(buflen, GFP_ATOMIC); - - vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid); - - if (recvlen > 0) { - icmsghdrp = (struct icmsg_hdr *)&buf[ - sizeof(struct vmbuspipe_hdr)]; - - prep_negotiate_resp(icmsghdrp, negop, buf); - - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION - | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, buf, - recvlen, requestid, - VM_PKT_DATA_INBAND, 0); - } - - kfree(buf); -} -EXPORT_SYMBOL(chn_cb_negotiate); - -/* - * Function table used for message responses for non IDE/SCSI/Network type - * messages. (Such as KVP/Shutdown etc) - */ -struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { - /* 0E0B6031-5213-4934-818B-38D90CED39DB */ - /* Shutdown */ - { - .msg_type = HV_SHUTDOWN_MSG, - .data.b = { - 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB - }, - .log_msg = "Shutdown channel functionality initialized" - }, - - /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ - /* TimeSync */ - { - .msg_type = HV_TIMESYNC_MSG, - .data.b = { - 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf - }, - .log_msg = "Timesync channel functionality initialized" - }, - /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ - /* Heartbeat */ - { - .msg_type = HV_HEARTBEAT_MSG, - .data.b = { - 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d - }, - .log_msg = "Heartbeat channel functionality initialized" - }, - /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ - /* KVP */ - { - .data.b = { - 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 - }, - .log_msg = "KVP channel functionality initialized" - }, -}; -EXPORT_SYMBOL(hv_cb_utils); - /* * alloc_channel - Allocate and initialize a vmbus channel object */ diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index 5c3e297..edaa9e2 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -581,11 +581,6 @@ struct vmbus_channel { struct work_struct work; enum vmbus_channel_state state; - /* - * For util channels, stash the - * the service index for easy access. - */ - s8 util_index; struct vmbus_channel_offer_channel offermsg; /* @@ -960,12 +955,6 @@ struct ictimesync_data { u8 flags; } __packed; -/* Index for each IC struct in array hv_cb_utils[] */ -#define HV_SHUTDOWN_MSG 0 -#define HV_TIMESYNC_MSG 1 -#define HV_HEARTBEAT_MSG 2 -#define HV_KVP_MSG 3 - struct hyperv_service_callback { u8 msg_type; char *log_msg; @@ -976,7 +965,5 @@ struct hyperv_service_callback { extern void prep_negotiate_resp(struct icmsg_hdr *, struct icmsg_negotiate *, u8 *); -extern void chn_cb_negotiate(void *); -extern struct hyperv_service_callback hv_cb_utils[]; #endif /* _HYPERV_H */ -- cgit v1.1 From 6519ad6e6f92a4310fbaab50f074d5bbad27b329 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 22 Sep 2011 12:40:50 -0700 Subject: Staging: hv: Update the TODO file Now that all vmbus audit related comments have been addressed, update the TODO file to reflect this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/TODO | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index 7c9a93f..fcc57c2 100644 --- a/drivers/staging/hv/TODO +++ b/drivers/staging/hv/TODO @@ -1,6 +1,4 @@ TODO: - - audit the vmbus to verify it is working properly with the - driver model - audit the network driver - checking for carrier inside open is wrong, network device API confusion?? -- cgit v1.1 From d515d0ff36a7afd528f32e3511780ad8385d957e Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Wed, 28 Sep 2011 13:24:15 -0700 Subject: staging: hv: remove the carrier status check from netvsc_open() Checking carrier status in netvsc_open() is not necessary. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/TODO | 2 -- drivers/staging/hv/netvsc_drv.c | 19 +++++++------------ 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index fcc57c2..ed4d636 100644 --- a/drivers/staging/hv/TODO +++ b/drivers/staging/hv/TODO @@ -1,7 +1,5 @@ TODO: - audit the network driver - - checking for carrier inside open is wrong, network device API - confusion?? - audit the scsi driver Please send patches for this code to Greg Kroah-Hartman , diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 69c233e..561ba58 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -69,20 +69,15 @@ static int netvsc_open(struct net_device *net) struct hv_device *device_obj = net_device_ctx->device_ctx; int ret = 0; - if (netif_carrier_ok(net)) { - /* Open up the device */ - ret = rndis_filter_open(device_obj); - if (ret != 0) { - netdev_err(net, "unable to open device (ret %d).\n", - ret); - return ret; - } - - netif_start_queue(net); - } else { - netdev_err(net, "unable to open device...link is down.\n"); + /* Open up the device */ + ret = rndis_filter_open(device_obj); + if (ret != 0) { + netdev_err(net, "unable to open device (ret %d).\n", ret); + return ret; } + netif_start_queue(net); + return ret; } -- cgit v1.1 From 870e53adbd372cbeea15ed00e1d4423725f3cea0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:41 -0700 Subject: Staging: hv: mousevsc: Fixup struct hv_input_dev_info This structure is protocol defined structure and must match the definition on the host side. Make appropriate adjustments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index fcb023a..44a2b23 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -30,10 +30,11 @@ * Data types */ struct hv_input_dev_info { + unsigned int size; unsigned short vendor; unsigned short product; unsigned short version; - char name[128]; + unsigned short reserved[11]; }; /* The maximum size of a synthetic input message. */ @@ -686,7 +687,7 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) hid_dev->dev = dev->device; sprintf(hid_dev->name, "%s", - input_device_ctx->device_info.name); + "Microsoft Vmbus HID-compliant Mouse"); /* * HJ Do we want to call it with a 0 @@ -763,7 +764,6 @@ static int mousevsc_on_device_add(struct hv_device *device, dev_info.vendor = input_dev->hid_dev_info.vendor; dev_info.product = input_dev->hid_dev_info.product; dev_info.version = input_dev->hid_dev_info.version; - strcpy(dev_info.name, "Microsoft Vmbus HID-compliant Mouse"); /* Send the device info back up */ input_device_ctx = dev_get_drvdata(&device->device); -- cgit v1.1 From 28e0d06655ddc6598155e2f71945f1abb00b398a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:42 -0700 Subject: Staging: hv: mousevsc: Get rid of the struct input_device_context The state maintained in struct input_device_context can easily be included in the struct mousevsc_dev structure. Simplify the code by consolidating the state. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 51 +++++++++++-------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 44a2b23..69eb00e 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -172,15 +172,11 @@ struct mousevsc_dev { unsigned char *report_desc; u32 report_desc_size; struct hv_input_dev_info hid_dev_info; -}; - -struct input_device_context { - struct hv_device *device_ctx; - struct hid_device *hid_device; - struct hv_input_dev_info device_info; int connected; + struct hid_device *hid_device; }; + static struct mousevsc_dev *alloc_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; @@ -402,7 +398,6 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, struct synthhid_input_report *input_report) { struct hv_driver *input_drv; - struct input_device_context *input_dev_ctx; if (!input_device->init_complete) { pr_info("Initialization incomplete...ignoring input_report msg"); @@ -411,9 +406,8 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, input_drv = drv_to_hv_drv(input_device->device->device.driver); - input_dev_ctx = dev_get_drvdata(&input_device->device->device); - hid_input_report(input_dev_ctx->hid_device, + hid_input_report(input_device->hid_device, HID_INPUT_REPORT, input_report->buffer, input_report->header.size, 1); } @@ -662,9 +656,8 @@ static void mousevsc_hid_close(struct hid_device *hid) static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) { - struct input_device_context *input_device_ctx = - dev_get_drvdata(&dev->device); struct hid_device *hid_dev; + struct mousevsc_dev *input_device = hv_get_drvdata(dev); /* hid_debug = -1; */ hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); @@ -681,9 +674,9 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) hid_dev->ll_driver->close = mousevsc_hid_close; hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_device_ctx->device_info.vendor; - hid_dev->product = input_device_ctx->device_info.product; - hid_dev->version = input_device_ctx->device_info.version; + hid_dev->vendor = input_device->hid_dev_info.vendor; + hid_dev->product = input_device->hid_dev_info.product; + hid_dev->version = input_device->hid_dev_info.version; hid_dev->dev = dev->device; sprintf(hid_dev->name, "%s", @@ -695,7 +688,7 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) if (!hidinput_connect(hid_dev, 0)) { hid_dev->claimed |= HID_CLAIMED_INPUT; - input_device_ctx->connected = 1; + input_device->connected = 1; DPRINT_INFO(INPUTVSC_DRV, "HID device claimed by input\n"); @@ -707,7 +700,7 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) "input or hiddev\n"); } - input_device_ctx->hid_device = hid_dev; + input_device->hid_device = hid_dev; } kfree(hid_dev); @@ -719,8 +712,6 @@ static int mousevsc_on_device_add(struct hv_device *device, int ret = 0; struct mousevsc_dev *input_dev; struct hv_driver *input_drv; - struct hv_input_dev_info dev_info; - struct input_device_context *input_device_ctx; input_dev = alloc_input_device(device); @@ -761,14 +752,7 @@ static int mousevsc_on_device_add(struct hv_device *device, input_drv = drv_to_hv_drv(input_dev->device->device.driver); - dev_info.vendor = input_dev->hid_dev_info.vendor; - dev_info.product = input_dev->hid_dev_info.product; - dev_info.version = input_dev->hid_dev_info.version; - /* Send the device info back up */ - input_device_ctx = dev_get_drvdata(&device->device); - memcpy(&input_device_ctx->device_info, &dev_info, - sizeof(struct hv_input_dev_info)); /* Send the report desc back up */ /* workaround SA-167 */ @@ -828,12 +812,6 @@ static int mousevsc_probe(struct hv_device *dev, { int ret = 0; - struct input_device_context *input_dev_ctx; - - input_dev_ctx = kmalloc(sizeof(struct input_device_context), - GFP_KERNEL); - - dev_set_drvdata(&dev->device, input_dev_ctx); /* Call to the vsc driver to add the device */ ret = mousevsc_on_device_add(dev, NULL); @@ -849,13 +827,12 @@ static int mousevsc_probe(struct hv_device *dev, static int mousevsc_remove(struct hv_device *dev) { - struct input_device_context *input_dev_ctx; + struct mousevsc_dev *input_dev = hv_get_drvdata(dev); int ret; - input_dev_ctx = dev_get_drvdata(&dev->device); - if (input_dev_ctx->connected) { - hidinput_disconnect(input_dev_ctx->hid_device); - input_dev_ctx->connected = 0; + if (input_dev->connected) { + hidinput_disconnect(input_dev->hid_device); + input_dev->connected = 0; } /* @@ -868,8 +845,6 @@ static int mousevsc_remove(struct hv_device *dev) "unable to remove vsc device (ret %d)", ret); } - kfree(input_dev_ctx); - return ret; } -- cgit v1.1 From 7f2bad4bd0d22f4cdd876152f1eeb9a8cfdc8d9d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:43 -0700 Subject: Staging: hv: mousevsc: Fixup some bogus WARN_ON() calls Fix the bogus WARN_ON() calls. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 69eb00e..016d7e5 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -200,7 +200,7 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) static void free_input_device(struct mousevsc_dev *device) { - WARN_ON(atomic_read(&device->ref_count) == 0); + WARN_ON(atomic_read(&device->ref_count) != 0); kfree(device); } @@ -327,7 +327,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Save the hid desc */ desc = &device_info->hid_descriptor; - WARN_ON(desc->bLength > 0); + WARN_ON(desc->bLength == 0); input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL); @@ -447,7 +447,7 @@ static void mousevsc_on_receive(struct hv_device *device, break; case SynthHidInitialDeviceInfo: - WARN_ON(pipe_msg->size >= sizeof(struct hv_input_dev_info)); + WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); /* * Parse out the device info into device attr, -- cgit v1.1 From 01584892dbf915a3921c5fc2607363e07023ef5c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:44 -0700 Subject: Staging: hv: mousevsc: Change the allocation flags to reflect interrupt context Change the allocation flags to reflect interrupt context. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 016d7e5..b7cc164 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -329,7 +329,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, desc = &device_info->hid_descriptor; WARN_ON(desc->bLength == 0); - input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL); + input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); if (!input_device->hid_desc) { pr_err("unable to allocate hid descriptor - size %d", @@ -342,7 +342,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Save the report desc */ input_device->report_desc_size = desc->desc[0].wDescriptorLength; input_device->report_desc = kzalloc(input_device->report_desc_size, - GFP_KERNEL); + GFP_ATOMIC); if (!input_device->report_desc) { pr_err("unable to allocate report descriptor - size %d", @@ -541,7 +541,7 @@ static void mousevsc_on_channel_callback(void *context) } else if (ret == -ENOBUFS) { /* Handle large packet */ bufferlen = bytes_recvd; - buffer = kzalloc(bytes_recvd, GFP_KERNEL); + buffer = kzalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { buffer = packet; -- cgit v1.1 From 60e8615ad6e09f47b15c4d023f728c112b8f7294 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:45 -0700 Subject: Staging: hv: mousevsc: Handle the case where we may get bogus report desc size Handle the case where we may get bogus report desc size from the host. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index b7cc164..19cfc23 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -341,6 +341,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Save the report desc */ input_device->report_desc_size = desc->desc[0].wDescriptorLength; + if (input_device->report_desc_size == 0) + goto cleanup; input_device->report_desc = kzalloc(input_device->report_desc_size, GFP_ATOMIC); -- cgit v1.1 From 1738067e5d7009c9ce9ee11c7fe9f9156b191aa9 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:46 -0700 Subject: Staging: hv: mousevsc: Correctly initialize the header size Correctly initialize the header size. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 19cfc23..74faa26 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -590,7 +590,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) request->size = sizeof(struct synthhid_protocol_request); request->request.header.type = SynthHidProtocolRequest; - request->request.header.size = sizeof(unsigned long); + request->request.header.size = sizeof(unsigned int); request->request.version_requested.version = SYNTHHID_INPUT_VERSION; pr_info("synthhid protocol request..."); -- cgit v1.1 From 622a50dce08bd817d2f10c1bcf806ccb35643653 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:47 -0700 Subject: Staging: hv: mousevsc: Use completion primitive to synchronize Use completion primitive to synchronize. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 74faa26..ea9e1f3 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -162,10 +162,7 @@ struct mousevsc_dev { struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; /* Synchronize the request/response if needed */ - wait_queue_head_t protocol_wait_event; - wait_queue_head_t dev_info_wait_event; - int protocol_wait_condition; - int device_wait_condition; + struct completion wait_event; int dev_info_status; struct hid_descriptor *hid_desc; @@ -194,6 +191,7 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) input_dev->device = device; hv_set_drvdata(device, input_dev); + init_completion(&input_dev->wait_event); return input_dev; } @@ -379,8 +377,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, goto cleanup; } - input_device->device_wait_condition = 1; - wake_up(&input_device->dev_info_wait_event); + complete(&input_device->wait_event); return; @@ -392,8 +389,7 @@ cleanup: input_device->report_desc = NULL; input_device->dev_info_status = -1; - input_device->device_wait_condition = 1; - wake_up(&input_device->dev_info_wait_event); + complete(&input_device->wait_event); } static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, @@ -444,8 +440,7 @@ static void mousevsc_on_receive(struct hv_device *device, memcpy(&input_dev->protocol_resp, pipe_msg, pipe_msg->size + sizeof(struct pipe_prt_msg) - sizeof(unsigned char)); - input_dev->protocol_wait_condition = 1; - wake_up(&input_dev->protocol_wait_event); + complete(&input_dev->wait_event); break; case SynthHidInitialDeviceInfo: @@ -565,6 +560,7 @@ static void mousevsc_on_channel_callback(void *context) static int mousevsc_connect_to_vsp(struct hv_device *device) { int ret = 0; + int t; struct mousevsc_dev *input_dev; struct mousevsc_prt_msg *request; struct mousevsc_prt_msg *response; @@ -576,8 +572,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) return -1; } - init_waitqueue_head(&input_dev->protocol_wait_event); - init_waitqueue_head(&input_dev->dev_info_wait_event); request = &input_dev->protocol_req; @@ -607,10 +601,8 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) goto cleanup; } - input_dev->protocol_wait_condition = 0; - wait_event_timeout(input_dev->protocol_wait_event, - input_dev->protocol_wait_condition, msecs_to_jiffies(1000)); - if (input_dev->protocol_wait_condition == 0) { + t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); + if (t == 0) { ret = -ETIMEDOUT; goto cleanup; } @@ -624,10 +616,8 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) goto cleanup; } - input_dev->device_wait_condition = 0; - wait_event_timeout(input_dev->dev_info_wait_event, - input_dev->device_wait_condition, msecs_to_jiffies(1000)); - if (input_dev->device_wait_condition == 0) { + t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); + if (t == 0) { ret = -ETIMEDOUT; goto cleanup; } -- cgit v1.1 From da5969e4cce5cbb44ca4597c7ff60bf6517ba00b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:48 -0700 Subject: Staging: hv: mousevsc: Cleanup and properly implement reportdesc_callback() Cleanup and properly implement reportdesc_callback(); properly allocate the hid_device and properly initialize the hid device structure. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 56 ++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 33 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index ea9e1f3..8d94aef 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -646,56 +646,45 @@ static void mousevsc_hid_close(struct hid_device *hid) { } +static struct hid_ll_driver mousevsc_ll_driver = { + .open = mousevsc_hid_open, + .close = mousevsc_hid_close, +}; + +static struct hid_driver mousevsc_hid_driver; + static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) { struct hid_device *hid_dev; struct mousevsc_dev *input_device = hv_get_drvdata(dev); - /* hid_debug = -1; */ - hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); + hid_dev = hid_allocate_device(); + if (IS_ERR(hid_dev)) + return; + + hid_dev->ll_driver = &mousevsc_ll_driver; + hid_dev->driver = &mousevsc_hid_driver; if (hid_parse_report(hid_dev, packet, len)) { DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); return; } - if (hid_dev) { - DPRINT_INFO(INPUTVSC_DRV, "hid_device created"); - - hid_dev->ll_driver->open = mousevsc_hid_open; - hid_dev->ll_driver->close = mousevsc_hid_close; + hid_dev->bus = BUS_VIRTUAL; + hid_dev->vendor = input_device->hid_dev_info.vendor; + hid_dev->product = input_device->hid_dev_info.product; + hid_dev->version = input_device->hid_dev_info.version; - hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_device->hid_dev_info.vendor; - hid_dev->product = input_device->hid_dev_info.product; - hid_dev->version = input_device->hid_dev_info.version; - hid_dev->dev = dev->device; + sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); - sprintf(hid_dev->name, "%s", - "Microsoft Vmbus HID-compliant Mouse"); + if (!hidinput_connect(hid_dev, 0)) { + hid_dev->claimed |= HID_CLAIMED_INPUT; - /* - * HJ Do we want to call it with a 0 - */ - if (!hidinput_connect(hid_dev, 0)) { - hid_dev->claimed |= HID_CLAIMED_INPUT; - - input_device->connected = 1; - - DPRINT_INFO(INPUTVSC_DRV, - "HID device claimed by input\n"); - } - - if (!hid_dev->claimed) { - DPRINT_ERR(INPUTVSC_DRV, - "HID device not claimed by " - "input or hiddev\n"); - } + input_device->connected = 1; - input_device->hid_device = hid_dev; } - kfree(hid_dev); + input_device->hid_device = hid_dev; } static int mousevsc_on_device_add(struct hv_device *device, @@ -825,6 +814,7 @@ static int mousevsc_remove(struct hv_device *dev) if (input_dev->connected) { hidinput_disconnect(input_dev->hid_device); input_dev->connected = 0; + hid_destroy_device(input_dev->hid_device); } /* -- cgit v1.1 From 0b1f0da005928c1cc761c320e6919b719a090a07 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:49 -0700 Subject: Staging: hv: mousevsc: Get rid of unnecessary DPRINT calls Get rid of unnecessary DPRINT calls. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 8d94aef..8dd902a 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -665,10 +665,8 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) hid_dev->ll_driver = &mousevsc_ll_driver; hid_dev->driver = &mousevsc_hid_driver; - if (hid_parse_report(hid_dev, packet, len)) { - DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); + if (hid_parse_report(hid_dev, packet, len)) return; - } hid_dev->bus = BUS_VIRTUAL; hid_dev->vendor = input_device->hid_dev_info.vendor; @@ -797,11 +795,8 @@ static int mousevsc_probe(struct hv_device *dev, /* Call to the vsc driver to add the device */ ret = mousevsc_on_device_add(dev, NULL); - if (ret != 0) { - DPRINT_ERR(INPUTVSC_DRV, "unable to add input vsc device"); - + if (ret != 0) return -1; - } return 0; } @@ -809,7 +804,6 @@ static int mousevsc_probe(struct hv_device *dev, static int mousevsc_remove(struct hv_device *dev) { struct mousevsc_dev *input_dev = hv_get_drvdata(dev); - int ret; if (input_dev->connected) { hidinput_disconnect(input_dev->hid_device); @@ -821,13 +815,7 @@ static int mousevsc_remove(struct hv_device *dev) * Call to the vsc driver to let it know that the device * is being removed */ - ret = mousevsc_on_device_remove(dev); - if (ret != 0) { - DPRINT_ERR(INPUTVSC_DRV, - "unable to remove vsc device (ret %d)", ret); - } - - return ret; + return mousevsc_on_device_remove(dev); } static const struct hv_vmbus_device_id id_table[] = { -- cgit v1.1 From 5cd4d0302cc3a53b4fb48006d448f44f666f1569 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:50 -0700 Subject: Staging: hv: mousevsc: Cleanup error handling Cleanup error handling in this driver; use standard Linux error codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 8dd902a..fc1f3e6 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -569,7 +569,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) if (!input_dev) { pr_err("unable to get input device...device being destroyed?"); - return -1; + return -ENODEV; } @@ -612,7 +612,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) if (!response->response.approved) { pr_err("synthhid protocol request failed (version %d)", SYNTHHID_INPUT_VERSION); - ret = -1; + ret = -ENODEV; goto cleanup; } @@ -629,7 +629,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) if (!input_dev->dev_info_status) pr_info("**** input channel up and running!! ****"); else - ret = -1; + ret = -ENOMEM; cleanup: put_input_device(device); @@ -694,10 +694,8 @@ static int mousevsc_on_device_add(struct hv_device *device, input_dev = alloc_input_device(device); - if (!input_dev) { - ret = -1; - goto cleanup; - } + if (!input_dev) + return -ENOMEM; input_dev->init_complete = false; @@ -714,7 +712,7 @@ static int mousevsc_on_device_add(struct hv_device *device, if (ret != 0) { pr_err("unable to open channel: %d", ret); free_input_device(input_dev); - return -1; + return ret; } pr_info("InputVsc channel open: %d", ret); @@ -743,7 +741,6 @@ static int mousevsc_on_device_add(struct hv_device *device, input_dev->init_complete = true; -cleanup: return ret; } @@ -789,16 +786,10 @@ static int mousevsc_on_device_remove(struct hv_device *device) static int mousevsc_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { - int ret = 0; - /* Call to the vsc driver to add the device */ - ret = mousevsc_on_device_add(dev, NULL); + return mousevsc_on_device_add(dev, NULL); - if (ret != 0) - return -1; - - return 0; } static int mousevsc_remove(struct hv_device *dev) -- cgit v1.1 From 61c4fb47cffa5cd6ff52fa1d3fca25547bcd76ad Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:51 -0700 Subject: Staging: hv: mousevsc: Get rid of unnecessary pr_* calls Get rid of unnecessary pr_* calls. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 64 ++++++++----------------------------------- 1 file changed, 11 insertions(+), 53 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index fc1f3e6..57bc4a3 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -294,10 +294,8 @@ static void mousevsc_on_send_completion(struct hv_device *device, void *request; input_dev = must_get_input_device(device); - if (!input_dev) { - pr_err("unable to get input device...device being destroyed?"); + if (!input_dev) return; - } request = (void *)(unsigned long)packet->trans_id; @@ -329,11 +327,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); - if (!input_device->hid_desc) { - pr_err("unable to allocate hid descriptor - size %d", - desc->bLength); + if (!input_device->hid_desc) goto cleanup; - } memcpy(input_device->hid_desc, desc, desc->bLength); @@ -344,11 +339,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, input_device->report_desc = kzalloc(input_device->report_desc_size, GFP_ATOMIC); - if (!input_device->report_desc) { - pr_err("unable to allocate report descriptor - size %d", - input_device->report_desc_size); + if (!input_device->report_desc) goto cleanup; - } memcpy(input_device->report_desc, ((unsigned char *)desc) + desc->bLength, @@ -371,11 +363,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, (unsigned long)&ack, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) { - pr_err("unable to send synthhid device info ack - ret %d", - ret); + if (ret != 0) goto cleanup; - } complete(&input_device->wait_event); @@ -397,10 +386,8 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, { struct hv_driver *input_drv; - if (!input_device->init_complete) { - pr_info("Initialization incomplete...ignoring input_report msg"); + if (!input_device->init_complete) return; - } input_drv = drv_to_hv_drv(input_device->device->device.driver); @@ -418,17 +405,13 @@ static void mousevsc_on_receive(struct hv_device *device, struct mousevsc_dev *input_dev; input_dev = must_get_input_device(device); - if (!input_dev) { - pr_err("unable to get input device...device being destroyed?"); + if (!input_dev) return; - } pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); if (pipe_msg->type != PipeMessageData) { - pr_err("unknown pipe msg type - type %d len %d", - pipe_msg->type, pipe_msg->size); put_input_device(device); return ; } @@ -483,10 +466,8 @@ static void mousevsc_on_channel_callback(void *context) input_dev = must_get_input_device(device); - if (!input_dev) { - pr_err("unable to get input device...device being destroyed?"); + if (!input_dev) return; - } do { ret = vmbus_recvpacket_raw(device->channel, buffer, @@ -545,8 +526,6 @@ static void mousevsc_on_channel_callback(void *context) bufferlen = packetSize; /* Try again next time around */ - pr_err("unable to allocate buffer of size %d!", - bytes_recvd); break; } } @@ -567,10 +546,8 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) input_dev = get_input_device(device); - if (!input_dev) { - pr_err("unable to get input device...device being destroyed?"); + if (!input_dev) return -ENODEV; - } request = &input_dev->protocol_req; @@ -587,7 +564,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) request->request.header.size = sizeof(unsigned int); request->request.version_requested.version = SYNTHHID_INPUT_VERSION; - pr_info("synthhid protocol request..."); ret = vmbus_sendpacket(device->channel, request, sizeof(struct pipe_prt_msg) - @@ -596,10 +572,8 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) { - pr_err("unable to send synthhid protocol request."); + if (ret != 0) goto cleanup; - } t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); if (t == 0) { @@ -626,9 +600,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) * We should have gotten the device attr, hid desc and report * desc at this point */ - if (!input_dev->dev_info_status) - pr_info("**** input channel up and running!! ****"); - else + if (input_dev->dev_info_status) ret = -ENOMEM; cleanup: @@ -710,18 +682,14 @@ static int mousevsc_on_device_add(struct hv_device *device, ); if (ret != 0) { - pr_err("unable to open channel: %d", ret); free_input_device(input_dev); return ret; } - pr_info("InputVsc channel open: %d", ret); ret = mousevsc_connect_to_vsp(device); if (ret != 0) { - pr_err("unable to connect channel: %d", ret); - vmbus_close(device->channel); free_input_device(input_dev); return ret; @@ -749,8 +717,6 @@ static int mousevsc_on_device_remove(struct hv_device *device) struct mousevsc_dev *input_dev; int ret = 0; - pr_info("disabling input device (%p)...", - hv_get_drvdata(device)); input_dev = release_input_device(device); @@ -761,19 +727,11 @@ static int mousevsc_on_device_remove(struct hv_device *device) * * so that outstanding requests can be completed. */ - while (input_dev->num_outstanding_req) { - pr_info("waiting for %d requests to complete...", - input_dev->num_outstanding_req); - + while (input_dev->num_outstanding_req) udelay(100); - } - - pr_info("removing input device (%p)...", hv_get_drvdata(device)); input_dev = final_release_input_device(device); - pr_info("input device (%p) safe to remove", input_dev); - /* Close the channel */ vmbus_close(device->channel); -- cgit v1.1 From ea8646b92feea6de86dae44a879364758b6a4dcb Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:52 -0700 Subject: Staging: hv: mousevsc: Free allocated memory in free_input_device() Free all allocated memory in free_input_device(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 57bc4a3..326d972 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -199,6 +199,8 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) static void free_input_device(struct mousevsc_dev *device) { WARN_ON(atomic_read(&device->ref_count) != 0); + kfree(device->hid_desc); + kfree(device->report_desc); kfree(device); } -- cgit v1.1 From c5b71fc71fc7cdee68614d37826ed46db9be2006 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:53 -0700 Subject: Staging: hv: mousevsc: Get rid of the unused state: num_outstanding_req Get rid of the unused state: num_outstanding_req in struct mousevsc_dev. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 326d972..092c0ff 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -157,7 +157,6 @@ struct mousevsc_dev { struct hv_device *device; /* 0 indicates the device is being destroyed */ atomic_t ref_count; - int num_outstanding_req; unsigned char init_complete; struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; @@ -729,8 +728,6 @@ static int mousevsc_on_device_remove(struct hv_device *device) * * so that outstanding requests can be completed. */ - while (input_dev->num_outstanding_req) - udelay(100); input_dev = final_release_input_device(device); -- cgit v1.1 From bdbbdb2d63fe340935ec6521da62fe9e73d8dc15 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:54 -0700 Subject: Staging: hv: mousevsc: Cleanup alloc_input_device() Cleanup alloc_input_device(); you can directly set the reference count. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 092c0ff..38e31ae 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -186,7 +186,7 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) * Set to 2 to allow both inbound and outbound traffics * (ie get_input_device() and must_get_input_device()) to proceed. */ - atomic_cmpxchg(&input_dev->ref_count, 0, 2); + atomic_set(&input_dev->ref_count, 2); input_dev->device = device; hv_set_drvdata(device, input_dev); -- cgit v1.1 From 1486dd0d0a95de1aaedd17ece19d9263ce7e5192 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:55 -0700 Subject: Staging: hv: mousevsc: Get rid of mousevsc_on_send_completion() We don't need to handle the "send complete" callback - nothing needs to be done here; get rid of the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 38e31ae..fc0ba68 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -288,25 +288,6 @@ static struct mousevsc_dev *final_release_input_device(struct hv_device *device) return input_dev; } -static void mousevsc_on_send_completion(struct hv_device *device, - struct vmpacket_descriptor *packet) -{ - struct mousevsc_dev *input_dev; - void *request; - - input_dev = must_get_input_device(device); - if (!input_dev) - return; - - request = (void *)(unsigned long)packet->trans_id; - - if (request == &input_dev->protocol_req) { - /* FIXME */ - /* Shouldn't we be doing something here? */ - } - - put_input_device(device); -} static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, struct synthhid_device_info *device_info) @@ -480,8 +461,6 @@ static void mousevsc_on_channel_callback(void *context) switch (desc->type) { case VM_PKT_COMP: - mousevsc_on_send_completion( - device, desc); break; case VM_PKT_DATA_INBAND: -- cgit v1.1 From 8660e38fab8b8a39ac828fb8a8579a9ad1b5d59d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:56 -0700 Subject: Staging: hv: mousevsc: Cleanup mousevsc_connect_to_vsp() Cleanup mousevsc_connect_to_vsp(). There is no need to take reference on the mousevsc device object when we are setting up the device. As part of this cleanup get rid of get_input_device() as this function is only used here. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index fc0ba68..75ea2db 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -204,32 +204,6 @@ static void free_input_device(struct mousevsc_dev *device) } /* - * Get the inputdevice object if exists and its refcount > 1 - */ -static struct mousevsc_dev *get_input_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = hv_get_drvdata(device); - -/* - * FIXME - * This sure isn't a valid thing to print for debugging, no matter - * what the intention is... - * - * printk(KERN_ERR "-------------------------> REFCOUNT = %d", - * input_dev->ref_count); - */ - - if (input_dev && atomic_read(&input_dev->ref_count) > 1) - atomic_inc(&input_dev->ref_count); - else - input_dev = NULL; - - return input_dev; -} - -/* * Get the inputdevice object iff exists and its refcount > 0 */ static struct mousevsc_dev *must_get_input_device(struct hv_device *device) @@ -520,15 +494,10 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) { int ret = 0; int t; - struct mousevsc_dev *input_dev; + struct mousevsc_dev *input_dev = hv_get_drvdata(device); struct mousevsc_prt_msg *request; struct mousevsc_prt_msg *response; - input_dev = get_input_device(device); - - if (!input_dev) - return -ENODEV; - request = &input_dev->protocol_req; @@ -584,7 +553,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) ret = -ENOMEM; cleanup: - put_input_device(device); return ret; } -- cgit v1.1 From 8ec31f9385fdcd7c71fa0078deb0e84840f3cb49 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:57 -0700 Subject: Staging: hv: mousevsc: Get rid of mousevsc_on_device_remove() by inlining code Get rid of mousevsc_on_device_remove() by inlining code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 47 ++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 75ea2db..5324429 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -660,33 +660,6 @@ static int mousevsc_on_device_add(struct hv_device *device, return ret; } -static int mousevsc_on_device_remove(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - int ret = 0; - - - input_dev = release_input_device(device); - - - /* - * At this point, all outbound traffic should be disable. We only - * allow inbound traffic (responses) to proceed - * - * so that outstanding requests can be completed. - */ - - input_dev = final_release_input_device(device); - - /* Close the channel */ - vmbus_close(device->channel); - - free_input_device(input_dev); - - return ret; -} - - static int mousevsc_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { @@ -706,11 +679,25 @@ static int mousevsc_remove(struct hv_device *dev) hid_destroy_device(input_dev->hid_device); } + + release_input_device(dev); + + /* - * Call to the vsc driver to let it know that the device - * is being removed + * At this point, all outbound traffic should be disable. We only + * allow inbound traffic (responses) to proceed + * + * so that outstanding requests can be completed. */ - return mousevsc_on_device_remove(dev); + + input_dev = final_release_input_device(dev); + + /* Close the channel */ + vmbus_close(dev->channel); + + free_input_device(input_dev); + + return 0; } static const struct hv_vmbus_device_id id_table[] = { -- cgit v1.1 From c411f17daf0942509f6db47b4a237e953f35611b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:58 -0700 Subject: Staging: hv: mousevsc: Now cleanup mousevsc_remove() Now, cleanup mousevsc_remove(). The mouse driver once initialized only receives data from the host. So, by closing the channel first in the unload path, we can properly deal with inflight packets. So, we don't need the machinery for managing the life-cycle of the mousevsc_dev object. Get rid of the unnecessary code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 53 +++---------------------------------------- 1 file changed, 3 insertions(+), 50 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 5324429..317d2be 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -197,9 +197,9 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) static void free_input_device(struct mousevsc_dev *device) { - WARN_ON(atomic_read(&device->ref_count) != 0); kfree(device->hid_desc); kfree(device->report_desc); + hv_set_drvdata(device->device, NULL); kfree(device); } @@ -229,39 +229,6 @@ static void put_input_device(struct hv_device *device) atomic_dec(&input_dev->ref_count); } -/* - * Drop ref count to 1 to effectively disable get_input_device() - */ -static struct mousevsc_dev *release_input_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = hv_get_drvdata(device); - - /* Busy wait until the ref drop to 2, then set it to 1 */ - while (atomic_cmpxchg(&input_dev->ref_count, 2, 1) != 2) - udelay(100); - - return input_dev; -} - -/* - * Drop ref count to 0. No one can use input_device object. - */ -static struct mousevsc_dev *final_release_input_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = hv_get_drvdata(device); - - /* Busy wait until the ref drop to 1, then set it to 0 */ - while (atomic_cmpxchg(&input_dev->ref_count, 1, 0) != 1) - udelay(100); - - hv_set_drvdata(device, NULL); - return input_dev; -} - static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, struct synthhid_device_info *device_info) @@ -673,28 +640,14 @@ static int mousevsc_remove(struct hv_device *dev) { struct mousevsc_dev *input_dev = hv_get_drvdata(dev); + vmbus_close(dev->channel); + if (input_dev->connected) { hidinput_disconnect(input_dev->hid_device); input_dev->connected = 0; hid_destroy_device(input_dev->hid_device); } - - release_input_device(dev); - - - /* - * At this point, all outbound traffic should be disable. We only - * allow inbound traffic (responses) to proceed - * - * so that outstanding requests can be completed. - */ - - input_dev = final_release_input_device(dev); - - /* Close the channel */ - vmbus_close(dev->channel); - free_input_device(input_dev); return 0; -- cgit v1.1 From ee2baa299ae11fec073c2b2aad7f6c571f71189e Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:54:59 -0700 Subject: Staging: hv: mousevsc: Get rid of ref_count state in struct mousevsc_dev Now get rid of the machinery for managing the life-cycle of the mousevsc_dev as this is not needed. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 54 +++---------------------------------------- 1 file changed, 3 insertions(+), 51 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 317d2be..e57e0b4 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -155,8 +155,6 @@ struct mousevsc_prt_msg { */ struct mousevsc_dev { struct hv_device *device; - /* 0 indicates the device is being destroyed */ - atomic_t ref_count; unsigned char init_complete; struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; @@ -182,12 +180,6 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) if (!input_dev) return NULL; - /* - * Set to 2 to allow both inbound and outbound traffics - * (ie get_input_device() and must_get_input_device()) to proceed. - */ - atomic_set(&input_dev->ref_count, 2); - input_dev->device = device; hv_set_drvdata(device, input_dev); init_completion(&input_dev->wait_event); @@ -203,32 +195,6 @@ static void free_input_device(struct mousevsc_dev *device) kfree(device); } -/* - * Get the inputdevice object iff exists and its refcount > 0 - */ -static struct mousevsc_dev *must_get_input_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = hv_get_drvdata(device); - - if (input_dev && atomic_read(&input_dev->ref_count)) - atomic_inc(&input_dev->ref_count); - else - input_dev = NULL; - - return input_dev; -} - -static void put_input_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = hv_get_drvdata(device); - - atomic_dec(&input_dev->ref_count); -} - static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, struct synthhid_device_info *device_info) @@ -325,19 +291,13 @@ static void mousevsc_on_receive(struct hv_device *device, { struct pipe_prt_msg *pipe_msg; struct synthhid_msg *hid_msg; - struct mousevsc_dev *input_dev; - - input_dev = must_get_input_device(device); - if (!input_dev) - return; + struct mousevsc_dev *input_dev = hv_get_drvdata(device); pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); - if (pipe_msg->type != PipeMessageData) { - put_input_device(device); - return ; - } + if (pipe_msg->type != PipeMessageData) + return; hid_msg = (struct synthhid_msg *)&pipe_msg->data[0]; @@ -370,7 +330,6 @@ static void mousevsc_on_receive(struct hv_device *device, break; } - put_input_device(device); } static void mousevsc_on_channel_callback(void *context) @@ -378,7 +337,6 @@ static void mousevsc_on_channel_callback(void *context) const int packetSize = 0x100; int ret = 0; struct hv_device *device = (struct hv_device *)context; - struct mousevsc_dev *input_dev; u32 bytes_recvd; u64 req_id; @@ -387,10 +345,6 @@ static void mousevsc_on_channel_callback(void *context) unsigned char *buffer = packet; int bufferlen = packetSize; - input_dev = must_get_input_device(device); - - if (!input_dev) - return; do { ret = vmbus_recvpacket_raw(device->channel, buffer, @@ -452,8 +406,6 @@ static void mousevsc_on_channel_callback(void *context) } } while (1); - put_input_device(device); - return; } -- cgit v1.1 From 517812b448e56d71185028445f8feb722bcd17a2 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:55:00 -0700 Subject: Staging: hv: mousevsc: Cleanup camel cased enums Cleanup all camel cased names. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index e57e0b4..6621326 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -58,12 +58,12 @@ struct hv_input_dev_info { * Message types in the synthetic input protocol */ enum synthhid_msg_type { - SynthHidProtocolRequest, - SynthHidProtocolResponse, - SynthHidInitialDeviceInfo, - SynthHidInitialDeviceInfoAck, - SynthHidInputReport, - SynthHidMax + SYNTH_HID_PROTOCOL_REQUEST, + SYNTH_HID_PROTOCOL_RESPONSE, + SYNTH_HID_INITIAL_DEVICE_INFO, + SYNTH_HID_INITIAL_DEVICE_INFO_ACK, + SYNTH_HID_INPUT_REPORT, + SYNTH_HID_MAX }; /* @@ -125,9 +125,9 @@ struct synthhid_input_report { #define NBITS(x) (((x)/BITS_PER_LONG)+1) enum pipe_prot_msg_type { - PipeMessageInvalid = 0, - PipeMessageData, - PipeMessageMaximum + PIPE_MESSAGE_INVALID, + PIPE_MESSAGE_DATA, + PIPE_MESSAGE_MAXIMUM }; @@ -238,10 +238,10 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Send the ack */ memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); - ack.type = PipeMessageData; + ack.type = PIPE_MESSAGE_DATA; ack.size = sizeof(struct synthhid_device_info_ack); - ack.ack.header.type = SynthHidInitialDeviceInfoAck; + ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; ack.ack.header.size = 1; ack.ack.reserved = 0; @@ -296,20 +296,20 @@ static void mousevsc_on_receive(struct hv_device *device, pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); - if (pipe_msg->type != PipeMessageData) + if (pipe_msg->type != PIPE_MESSAGE_DATA) return; hid_msg = (struct synthhid_msg *)&pipe_msg->data[0]; switch (hid_msg->header.type) { - case SynthHidProtocolResponse: + case SYNTH_HID_PROTOCOL_RESPONSE: memcpy(&input_dev->protocol_resp, pipe_msg, pipe_msg->size + sizeof(struct pipe_prt_msg) - sizeof(unsigned char)); complete(&input_dev->wait_event); break; - case SynthHidInitialDeviceInfo: + case SYNTH_HID_INITIAL_DEVICE_INFO: WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); /* @@ -319,7 +319,7 @@ static void mousevsc_on_receive(struct hv_device *device, mousevsc_on_receive_device_info(input_dev, (struct synthhid_device_info *)&pipe_msg->data[0]); break; - case SynthHidInputReport: + case SYNTH_HID_INPUT_REPORT: mousevsc_on_receive_input_report(input_dev, (struct synthhid_input_report *)&pipe_msg->data[0]); @@ -425,10 +425,10 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) */ memset(request, 0, sizeof(struct mousevsc_prt_msg)); - request->type = PipeMessageData; + request->type = PIPE_MESSAGE_DATA; request->size = sizeof(struct synthhid_protocol_request); - request->request.header.type = SynthHidProtocolRequest; + request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; request->request.header.size = sizeof(unsigned int); request->request.version_requested.version = SYNTHHID_INPUT_VERSION; -- cgit v1.1 From 6e56f27c09ec695fd0091476772e38fe9ccaa5a9 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:55:01 -0700 Subject: Staging: hv: mousevsc: Get rid of mousevsc_on_receive_input_report() by inlining Get rid of mousevsc_on_receive_input_report() by inlining the code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 6621326..a526ba5 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -270,28 +270,13 @@ cleanup: complete(&input_device->wait_event); } -static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, - struct synthhid_input_report *input_report) -{ - struct hv_driver *input_drv; - - if (!input_device->init_complete) - return; - - input_drv = drv_to_hv_drv(input_device->device->device.driver); - - - hid_input_report(input_device->hid_device, - HID_INPUT_REPORT, input_report->buffer, input_report->header.size, 1); - -} - static void mousevsc_on_receive(struct hv_device *device, struct vmpacket_descriptor *packet) { struct pipe_prt_msg *pipe_msg; struct synthhid_msg *hid_msg; struct mousevsc_dev *input_dev = hv_get_drvdata(device); + struct synthhid_input_report *input_report; pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); @@ -320,9 +305,13 @@ static void mousevsc_on_receive(struct hv_device *device, (struct synthhid_device_info *)&pipe_msg->data[0]); break; case SYNTH_HID_INPUT_REPORT: - mousevsc_on_receive_input_report(input_dev, - (struct synthhid_input_report *)&pipe_msg->data[0]); - + input_report = + (struct synthhid_input_report *)&pipe_msg->data[0]; + if (!input_dev->init_complete) + break; + hid_input_report(input_dev->hid_device, + HID_INPUT_REPORT, input_report->buffer, + input_report->header.size, 1); break; default: pr_err("unsupported hid msg type - type %d len %d", -- cgit v1.1 From 929ad795f0a8d3419ea19c76d7c13ebb96c49286 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:55:02 -0700 Subject: Staging: hv: mousevsc: Cleanup mousevsc_on_device_add() Cleanup mousevsc_on_device_add(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index a526ba5..98ae062 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -513,12 +513,10 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) input_device->hid_device = hid_dev; } -static int mousevsc_on_device_add(struct hv_device *device, - void *additional_info) +static int mousevsc_on_device_add(struct hv_device *device) { int ret = 0; struct mousevsc_dev *input_dev; - struct hv_driver *input_drv; input_dev = alloc_input_device(device); @@ -551,9 +549,6 @@ static int mousevsc_on_device_add(struct hv_device *device, return ret; } - input_drv = drv_to_hv_drv(input_dev->device->device.driver); - - /* Send the report desc back up */ /* workaround SA-167 */ @@ -573,7 +568,7 @@ static int mousevsc_probe(struct hv_device *dev, { /* Call to the vsc driver to add the device */ - return mousevsc_on_device_add(dev, NULL); + return mousevsc_on_device_add(dev); } -- cgit v1.1 From 1eadd8c286824ab50298bc6c828d4984bd297e9f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:55:03 -0700 Subject: Staging: hv: mousevsc: Enable autoloading of the mouse driver Now that the mouse driver is functional, enable the auto-loading of the driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 98ae062..71b460b 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -596,10 +596,7 @@ static const struct hv_vmbus_device_id id_table[] = { { }, }; -/* - * The mouse driver is not functional; do not auto-load it. - */ -/* MODULE_DEVICE_TABLE(vmbus, id_table); */ +MODULE_DEVICE_TABLE(vmbus, id_table); static struct hv_driver mousevsc_drv = { .name = "mousevsc", -- cgit v1.1 From 41598a0b718d31db6782a87ac5049ccfb56121db Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 29 Sep 2011 11:55:04 -0700 Subject: Staging: hv: mousevsc: Get rid of unnecessary comments Get rid of unnecessary comments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 71b460b..edbb479 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -26,9 +26,6 @@ #include "hyperv.h" -/* - * Data types - */ struct hv_input_dev_info { unsigned int size; unsigned short vendor; @@ -137,9 +134,6 @@ struct pipe_prt_msg { char data[1]; }; -/* - * Data types - */ struct mousevsc_prt_msg { enum pipe_prot_msg_type type; u32 size; @@ -206,11 +200,9 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Assume success for now */ input_device->dev_info_status = 0; - /* Save the device attr */ memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info, sizeof(struct hv_input_dev_info)); - /* Save the hid desc */ desc = &device_info->hid_descriptor; WARN_ON(desc->bLength == 0); @@ -221,7 +213,6 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, memcpy(input_device->hid_desc, desc, desc->bLength); - /* Save the report desc */ input_device->report_desc_size = desc->desc[0].wDescriptorLength; if (input_device->report_desc_size == 0) goto cleanup; @@ -368,10 +359,6 @@ static void mousevsc_on_channel_callback(void *context) bufferlen = packetSize; } } else { - /* - * pr_debug("nothing else to read..."); - * reset - */ if (bufferlen > packetSize) { kfree(buffer); @@ -388,8 +375,6 @@ static void mousevsc_on_channel_callback(void *context) if (buffer == NULL) { buffer = packet; bufferlen = packetSize; - - /* Try again next time around */ break; } } @@ -409,9 +394,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) request = &input_dev->protocol_req; - /* - * Now, initiate the vsc/vsp initialization protocol on the open channel - */ memset(request, 0, sizeof(struct mousevsc_prt_msg)); request->type = PIPE_MESSAGE_DATA; @@ -525,7 +507,6 @@ static int mousevsc_on_device_add(struct hv_device *device) input_dev->init_complete = false; - /* Open the channel */ ret = vmbus_open(device->channel, INPUTVSC_SEND_RING_BUFFER_SIZE, INPUTVSC_RECV_RING_BUFFER_SIZE, @@ -550,7 +531,6 @@ static int mousevsc_on_device_add(struct hv_device *device) } - /* Send the report desc back up */ /* workaround SA-167 */ if (input_dev->report_desc[14] == 0x25) input_dev->report_desc[14] = 0x29; @@ -567,7 +547,6 @@ static int mousevsc_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { - /* Call to the vsc driver to add the device */ return mousevsc_on_device_add(dev); } -- cgit v1.1 From 76e5f8135d63eb784ef44438e46e82cf0329e179 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 4 Oct 2011 14:00:02 -0700 Subject: Staging: hv: util: Fix a bug in kvp implementation The host gurantees that there can be only one kvp transaction active against the guest. So, the transaction active state is needed only to protect against spurious user level calls. The current code had a race condition where the guest could prematurely return because the previous transaction state was not cleared - this state was being cleared after sending the response to the host and there was a window where the host could notify the guest of a new transaction before the transaction active state was properly set. Also deal with the case when the user mode component does not respond in a timely fashion correctly. I would like to thank Long Li for identifying the problem. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Diagnosed-by: Long Li Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_kvp.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index 9aa9ede..307aedc 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c @@ -50,6 +50,8 @@ static struct { static int kvp_send_key(int index); +#define TIMEOUT_FIRED 1 + static void kvp_respond_to_host(char *key, char *value, int error); static void kvp_work_func(struct work_struct *dummy); static void kvp_register(void); @@ -58,7 +60,6 @@ static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; static const char kvp_name[] = "kvp_kernel_module"; -static int timeout_fired; static u8 *recv_buffer; /* * Register the kernel component with the user-level daemon. @@ -90,8 +91,7 @@ kvp_work_func(struct work_struct *dummy) * If the timer fires, the user-mode component has not responded; * process the pending transaction. */ - kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired); - timeout_fired = 1; + kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); } /* @@ -177,6 +177,8 @@ kvp_respond_to_host(char *key, char *value, int error) channel = kvp_transaction.recv_channel; req_id = kvp_transaction.recv_req_id; + kvp_transaction.active = false; + if (channel->onchannel_callback == NULL) /* * We have raced with util driver being unloaded; @@ -224,7 +226,6 @@ response_done: vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, VM_PKT_DATA_INBAND, 0); - kvp_transaction.active = false; } /* @@ -250,10 +251,6 @@ void hv_kvp_onchannelcallback(void *context) struct icmsg_negotiate *negop = NULL; - if (kvp_transaction.active) - return; - - vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { -- cgit v1.1 From e2bb65378385a10e21612845e33cd5936e0cbadb Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 9 Oct 2011 19:42:28 -0700 Subject: Staging: hv: util: Invoke cn_netlink_send() in a work context Invoke cn_netlink_send() in a work context as opposed being called in the context of channel callback. On entry into the channel callback code the channel inbound spin lock is held and deferring to a work context avoids having to invoke cn_netlink_send() while holding the inbound lock. As part of this adjustment, also increase the timeout value for waiting for the user level component of KVP. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_kvp.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index 307aedc..1e9515c 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c @@ -44,11 +44,12 @@ static struct { bool active; /* transaction status - active or not */ int recv_len; /* number of bytes received. */ + int index; /* current index */ struct vmbus_channel *recv_channel; /* chn we got the request */ u64 recv_req_id; /* request ID. */ } kvp_transaction; -static int kvp_send_key(int index); +static void kvp_send_key(struct work_struct *dummy); #define TIMEOUT_FIRED 1 @@ -57,6 +58,7 @@ static void kvp_work_func(struct work_struct *dummy); static void kvp_register(void); static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); +static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; static const char kvp_name[] = "kvp_kernel_module"; @@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) } } -static int -kvp_send_key(int index) +static void +kvp_send_key(struct work_struct *dummy) { struct cn_msg *msg; + int index = kvp_transaction.index; msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); @@ -136,9 +139,8 @@ kvp_send_key(int index) msg->len = sizeof(struct hv_ku_msg); cn_netlink_send(msg, 0, GFP_ATOMIC); kfree(msg); - return 0; } - return 1; + return; } /* @@ -286,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context) kvp_transaction.recv_channel = channel; kvp_transaction.recv_req_id = requestid; kvp_transaction.active = true; + kvp_transaction.index = kvp_data->index; /* * Get the information from the @@ -296,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context) * Set a timeout to deal with * user-mode not responding. */ - kvp_send_key(kvp_data->index); - schedule_delayed_work(&kvp_work, 100); + schedule_work(&kvp_sendkey_work); + schedule_delayed_work(&kvp_work, 5*HZ); return; @@ -332,4 +335,5 @@ void hv_kvp_deinit(void) { cn_del_callback(&kvp_id); cancel_delayed_work_sync(&kvp_work); + cancel_work_sync(&kvp_sendkey_work); } -- cgit v1.1 From 92ae4ebdaa6d6d083a53421715e5cdc70ab5823e Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 10 Oct 2011 09:37:39 +0200 Subject: staging: hv: storvsc: ignore SET_WINDOW scsi command Some commands sent by smartd will offline the device. With this change applied, smartd sill not monitor the device anymore. Signed-off-by: Olaf Hering Acked-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 807c94d..e412716 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1122,6 +1122,22 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) kmem_cache_free(host_dev->request_pool, cmd_request); } +static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) +{ + bool allowed = true; + u8 scsi_op = scmnd->cmnd[0]; + + switch (scsi_op) { + /* smartd sends this command, which will offline the device */ + case SET_WINDOW: + scmnd->result = DID_ERROR << 16; + allowed = false; + break; + default: + break; + } + return allowed; +} /* * storvsc_queuecommand - Initiate command processing @@ -1141,6 +1157,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, unsigned int sg_count = 0; struct vmscsi_request *vm_srb; + if (storvsc_check_scsi_cmd(scmnd) == false) { + done(scmnd); + return 0; + } /* If retrying, no need to prep the cmd */ if (scmnd->host_scribble) { -- cgit v1.1 From 715a4801e734ea9c8e528265ce3ff6aead85bce1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 6 Oct 2011 10:10:56 -0700 Subject: Staging: hv: netvsc: Fix a dereferencing issue net_dev is being de-referenced without proper checking; fix it. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/rndis_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index ef43f2e..bafccb3 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -368,11 +368,11 @@ int rndis_filter_receive(struct hv_device *dev, struct rndis_message *rndis_hdr; struct net_device *ndev; - ndev = net_dev->ndev; - if (!net_dev) return -EINVAL; + ndev = net_dev->ndev; + /* Make sure the rndis device state is initialized */ if (!net_dev->extension) { netdev_err(ndev, "got rndis message but no rndis device - " -- cgit v1.1 From 46a971913611a23478283931460a95be962ce329 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 4 Oct 2011 12:29:52 -0700 Subject: Staging: hv: move hyperv code out of staging directory After many years wandering the desert, it is finally time for the Microsoft HyperV code to move out of the staging directory. Or at least the core hyperv bus code, and the utility driver, the rest still have some review to get through by the various subsystem maintainers. Signed-off-by: Greg Kroah-Hartman Signed-off-by: K. Y. Srinivasan --- drivers/staging/hv/Kconfig | 28 +- drivers/staging/hv/Makefile | 7 +- drivers/staging/hv/channel.c | 815 -------------------------- drivers/staging/hv/channel_mgmt.c | 647 --------------------- drivers/staging/hv/connection.c | 318 ---------- drivers/staging/hv/hv.c | 429 -------------- drivers/staging/hv/hv_kvp.c | 339 ----------- drivers/staging/hv/hv_kvp.h | 184 ------ drivers/staging/hv/hv_mouse.c | 3 +- drivers/staging/hv/hv_util.c | 354 ----------- drivers/staging/hv/hyperv.h | 969 ------------------------------- drivers/staging/hv/hyperv_net.h | 2 +- drivers/staging/hv/hyperv_vmbus.h | 629 -------------------- drivers/staging/hv/ring_buffer.c | 527 ----------------- drivers/staging/hv/storvsc_drv.c | 2 +- drivers/staging/hv/tools/hv_kvp_daemon.c | 500 ---------------- drivers/staging/hv/vmbus_drv.c | 772 ------------------------ 17 files changed, 7 insertions(+), 6518 deletions(-) delete mode 100644 drivers/staging/hv/channel.c delete mode 100644 drivers/staging/hv/channel_mgmt.c delete mode 100644 drivers/staging/hv/connection.c delete mode 100644 drivers/staging/hv/hv.c delete mode 100644 drivers/staging/hv/hv_kvp.c delete mode 100644 drivers/staging/hv/hv_kvp.h delete mode 100644 drivers/staging/hv/hv_util.c delete mode 100644 drivers/staging/hv/hyperv.h delete mode 100644 drivers/staging/hv/hyperv_vmbus.h delete mode 100644 drivers/staging/hv/ring_buffer.c delete mode 100644 drivers/staging/hv/tools/hv_kvp_daemon.c delete mode 100644 drivers/staging/hv/vmbus_drv.c (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig index 815f8c2..072185e 100644 --- a/drivers/staging/hv/Kconfig +++ b/drivers/staging/hv/Kconfig @@ -1,39 +1,17 @@ -config HYPERV - tristate "Microsoft Hyper-V client drivers" - depends on X86 && ACPI && PCI - default n - help - Select this option to run Linux as a Hyper-V client operating - system. - -if HYPERV - config HYPERV_STORAGE tristate "Microsoft Hyper-V virtual storage driver" - depends on SCSI - default HYPERV + depends on HYPERV && SCSI help Select this option to enable the Hyper-V virtual storage driver. config HYPERV_NET tristate "Microsoft Hyper-V virtual network driver" - depends on NET - default HYPERV + depends on HYPERV && NET help Select this option to enable the Hyper-V virtual network driver. -config HYPERV_UTILS - tristate "Microsoft Hyper-V Utilities driver" - depends on CONNECTOR && NLS - default HYPERV - help - Select this option to enable the Hyper-V Utilities. - config HYPERV_MOUSE tristate "Microsoft Hyper-V mouse driver" - depends on HID - default HYPERV + depends on HYPERV && HID help Select this option to enable the Hyper-V mouse driver. - -endif diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile index bd176b1..e071c12 100644 --- a/drivers/staging/hv/Makefile +++ b/drivers/staging/hv/Makefile @@ -1,12 +1,7 @@ -obj-$(CONFIG_HYPERV) += hv_vmbus.o hv_timesource.o +obj-$(CONFIG_HYPERV) += hv_timesource.o obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o -obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o -hv_vmbus-y := vmbus_drv.o \ - hv.o connection.o channel.o \ - channel_mgmt.o ring_buffer.o hv_storvsc-y := storvsc_drv.o hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o -hv_utils-y := hv_util.o hv_kvp.o diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c deleted file mode 100644 index b6f3d38..0000000 --- a/drivers/staging/hv/channel.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - -#define NUM_PAGES_SPANNED(addr, len) \ -((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT)) - -/* Internal routines */ -static int create_gpadl_header( - void *kbuffer, /* must be phys and virt contiguous */ - u32 size, /* page-size multiple */ - struct vmbus_channel_msginfo **msginfo, - u32 *messagecount); -static void vmbus_setevent(struct vmbus_channel *channel); - -/* - * vmbus_setevent- Trigger an event notification on the specified - * channel. - */ -static void vmbus_setevent(struct vmbus_channel *channel) -{ - struct hv_monitor_page *monitorpage; - - if (channel->offermsg.monitor_allocated) { - /* Each u32 represents 32 channels */ - sync_set_bit(channel->offermsg.child_relid & 31, - (unsigned long *) vmbus_connection.send_int_page + - (channel->offermsg.child_relid >> 5)); - - monitorpage = vmbus_connection.monitor_pages; - monitorpage++; /* Get the child to parent monitor page */ - - sync_set_bit(channel->monitor_bit, - (unsigned long *)&monitorpage->trigger_group - [channel->monitor_grp].pending); - - } else { - vmbus_set_event(channel->offermsg.child_relid); - } -} - -/* - * vmbus_get_debug_info -Retrieve various channel debug info - */ -void vmbus_get_debug_info(struct vmbus_channel *channel, - struct vmbus_channel_debug_info *debuginfo) -{ - struct hv_monitor_page *monitorpage; - u8 monitor_group = (u8)channel->offermsg.monitorid / 32; - u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - - debuginfo->relid = channel->offermsg.child_relid; - debuginfo->state = channel->state; - memcpy(&debuginfo->interfacetype, - &channel->offermsg.offer.if_type, sizeof(uuid_le)); - memcpy(&debuginfo->interface_instance, - &channel->offermsg.offer.if_instance, - sizeof(uuid_le)); - - monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; - - debuginfo->monitorid = channel->offermsg.monitorid; - - debuginfo->servermonitor_pending = - monitorpage->trigger_group[monitor_group].pending; - debuginfo->servermonitor_latency = - monitorpage->latency[monitor_group][monitor_offset]; - debuginfo->servermonitor_connectionid = - monitorpage->parameter[monitor_group] - [monitor_offset].connectionid.u.id; - - monitorpage++; - - debuginfo->clientmonitor_pending = - monitorpage->trigger_group[monitor_group].pending; - debuginfo->clientmonitor_latency = - monitorpage->latency[monitor_group][monitor_offset]; - debuginfo->clientmonitor_connectionid = - monitorpage->parameter[monitor_group] - [monitor_offset].connectionid.u.id; - - hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound); - hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound); -} - -/* - * vmbus_open - Open the specified channel. - */ -int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, - u32 recv_ringbuffer_size, void *userdata, u32 userdatalen, - void (*onchannelcallback)(void *context), void *context) -{ - struct vmbus_channel_open_channel *open_msg; - struct vmbus_channel_msginfo *open_info = NULL; - void *in, *out; - unsigned long flags; - int ret, t, err = 0; - - newchannel->onchannel_callback = onchannelcallback; - newchannel->channel_callback_context = context; - - /* Allocate the ring buffer */ - out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, - get_order(send_ringbuffer_size + recv_ringbuffer_size)); - - if (!out) - return -ENOMEM; - - - in = (void *)((unsigned long)out + send_ringbuffer_size); - - newchannel->ringbuffer_pages = out; - newchannel->ringbuffer_pagecount = (send_ringbuffer_size + - recv_ringbuffer_size) >> PAGE_SHIFT; - - ret = hv_ringbuffer_init( - &newchannel->outbound, out, send_ringbuffer_size); - - if (ret != 0) { - err = ret; - goto errorout; - } - - ret = hv_ringbuffer_init( - &newchannel->inbound, in, recv_ringbuffer_size); - if (ret != 0) { - err = ret; - goto errorout; - } - - - /* Establish the gpadl for the ring buffer */ - newchannel->ringbuffer_gpadlhandle = 0; - - ret = vmbus_establish_gpadl(newchannel, - newchannel->outbound.ring_buffer, - send_ringbuffer_size + - recv_ringbuffer_size, - &newchannel->ringbuffer_gpadlhandle); - - if (ret != 0) { - err = ret; - goto errorout; - } - - /* Create and init the channel open message */ - open_info = kmalloc(sizeof(*open_info) + - sizeof(struct vmbus_channel_open_channel), - GFP_KERNEL); - if (!open_info) { - err = -ENOMEM; - goto errorout; - } - - init_completion(&open_info->waitevent); - - open_msg = (struct vmbus_channel_open_channel *)open_info->msg; - open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL; - open_msg->openid = newchannel->offermsg.child_relid; - open_msg->child_relid = newchannel->offermsg.child_relid; - open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle; - open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >> - PAGE_SHIFT; - open_msg->server_contextarea_gpadlhandle = 0; - - if (userdatalen > MAX_USER_DEFINED_BYTES) { - err = -EINVAL; - goto errorout; - } - - if (userdatalen) - memcpy(open_msg->userdata, userdata, userdatalen); - - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_add_tail(&open_info->msglistentry, - &vmbus_connection.chn_msg_list); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - ret = vmbus_post_msg(open_msg, - sizeof(struct vmbus_channel_open_channel)); - - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); - if (t == 0) { - err = -ETIMEDOUT; - goto errorout; - } - - - if (open_info->response.open_result.status) - err = open_info->response.open_result.status; - -cleanup: - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&open_info->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - kfree(open_info); - return err; - -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); - free_pages((unsigned long)out, - get_order(send_ringbuffer_size + recv_ringbuffer_size)); - kfree(open_info); - return err; -} -EXPORT_SYMBOL_GPL(vmbus_open); - -/* - * create_gpadl_header - Creates a gpadl for the specified buffer - */ -static int create_gpadl_header(void *kbuffer, u32 size, - struct vmbus_channel_msginfo **msginfo, - u32 *messagecount) -{ - int i; - int pagecount; - unsigned long long pfn; - struct vmbus_channel_gpadl_header *gpadl_header; - struct vmbus_channel_gpadl_body *gpadl_body; - struct vmbus_channel_msginfo *msgheader; - struct vmbus_channel_msginfo *msgbody = NULL; - u32 msgsize; - - int pfnsum, pfncount, pfnleft, pfncurr, pfnsize; - - pagecount = size >> PAGE_SHIFT; - pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT; - - /* do we need a gpadl body msg */ - pfnsize = MAX_SIZE_CHANNEL_MESSAGE - - sizeof(struct vmbus_channel_gpadl_header) - - sizeof(struct gpa_range); - pfncount = pfnsize / sizeof(u64); - - if (pagecount > pfncount) { - /* we need a gpadl body */ - /* fill in the header */ - msgsize = sizeof(struct vmbus_channel_msginfo) + - sizeof(struct vmbus_channel_gpadl_header) + - sizeof(struct gpa_range) + pfncount * sizeof(u64); - msgheader = kzalloc(msgsize, GFP_KERNEL); - if (!msgheader) - goto nomem; - - INIT_LIST_HEAD(&msgheader->submsglist); - msgheader->msgsize = msgsize; - - gpadl_header = (struct vmbus_channel_gpadl_header *) - msgheader->msg; - gpadl_header->rangecount = 1; - gpadl_header->range_buflen = sizeof(struct gpa_range) + - pagecount * sizeof(u64); - gpadl_header->range[0].byte_offset = 0; - gpadl_header->range[0].byte_count = size; - for (i = 0; i < pfncount; i++) - gpadl_header->range[0].pfn_array[i] = pfn+i; - *msginfo = msgheader; - *messagecount = 1; - - pfnsum = pfncount; - pfnleft = pagecount - pfncount; - - /* how many pfns can we fit */ - pfnsize = MAX_SIZE_CHANNEL_MESSAGE - - sizeof(struct vmbus_channel_gpadl_body); - pfncount = pfnsize / sizeof(u64); - - /* fill in the body */ - while (pfnleft) { - if (pfnleft > pfncount) - pfncurr = pfncount; - else - pfncurr = pfnleft; - - msgsize = sizeof(struct vmbus_channel_msginfo) + - sizeof(struct vmbus_channel_gpadl_body) + - pfncurr * sizeof(u64); - msgbody = kzalloc(msgsize, GFP_KERNEL); - - if (!msgbody) { - struct vmbus_channel_msginfo *pos = NULL; - struct vmbus_channel_msginfo *tmp = NULL; - /* - * Free up all the allocated messages. - */ - list_for_each_entry_safe(pos, tmp, - &msgheader->submsglist, - msglistentry) { - - list_del(&pos->msglistentry); - kfree(pos); - } - - goto nomem; - } - - msgbody->msgsize = msgsize; - (*messagecount)++; - gpadl_body = - (struct vmbus_channel_gpadl_body *)msgbody->msg; - - /* - * Gpadl is u32 and we are using a pointer which could - * be 64-bit - * This is governed by the guest/host protocol and - * so the hypervisor gurantees that this is ok. - */ - for (i = 0; i < pfncurr; i++) - gpadl_body->pfn[i] = pfn + pfnsum + i; - - /* add to msg header */ - list_add_tail(&msgbody->msglistentry, - &msgheader->submsglist); - pfnsum += pfncurr; - pfnleft -= pfncurr; - } - } else { - /* everything fits in a header */ - msgsize = sizeof(struct vmbus_channel_msginfo) + - sizeof(struct vmbus_channel_gpadl_header) + - sizeof(struct gpa_range) + pagecount * sizeof(u64); - msgheader = kzalloc(msgsize, GFP_KERNEL); - if (msgheader == NULL) - goto nomem; - msgheader->msgsize = msgsize; - - gpadl_header = (struct vmbus_channel_gpadl_header *) - msgheader->msg; - gpadl_header->rangecount = 1; - gpadl_header->range_buflen = sizeof(struct gpa_range) + - pagecount * sizeof(u64); - gpadl_header->range[0].byte_offset = 0; - gpadl_header->range[0].byte_count = size; - for (i = 0; i < pagecount; i++) - gpadl_header->range[0].pfn_array[i] = pfn+i; - - *msginfo = msgheader; - *messagecount = 1; - } - - return 0; -nomem: - kfree(msgheader); - kfree(msgbody); - return -ENOMEM; -} - -/* - * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer - * - * @channel: a channel - * @kbuffer: from kmalloc - * @size: page-size multiple - * @gpadl_handle: some funky thing - */ -int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, - u32 size, u32 *gpadl_handle) -{ - struct vmbus_channel_gpadl_header *gpadlmsg; - struct vmbus_channel_gpadl_body *gpadl_body; - struct vmbus_channel_msginfo *msginfo = NULL; - struct vmbus_channel_msginfo *submsginfo; - u32 msgcount; - struct list_head *curr; - u32 next_gpadl_handle; - unsigned long flags; - int ret = 0; - int t; - - next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle); - atomic_inc(&vmbus_connection.next_gpadl_handle); - - ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount); - if (ret) - return ret; - - init_completion(&msginfo->waitevent); - - gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg; - gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER; - gpadlmsg->child_relid = channel->offermsg.child_relid; - gpadlmsg->gpadl = next_gpadl_handle; - - - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_add_tail(&msginfo->msglistentry, - &vmbus_connection.chn_msg_list); - - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize - - sizeof(*msginfo)); - if (ret != 0) - goto cleanup; - - if (msgcount > 1) { - list_for_each(curr, &msginfo->submsglist) { - - submsginfo = (struct vmbus_channel_msginfo *)curr; - gpadl_body = - (struct vmbus_channel_gpadl_body *)submsginfo->msg; - - gpadl_body->header.msgtype = - CHANNELMSG_GPADL_BODY; - gpadl_body->gpadl = next_gpadl_handle; - - ret = vmbus_post_msg(gpadl_body, - submsginfo->msgsize - - sizeof(*submsginfo)); - if (ret != 0) - goto cleanup; - - } - } - t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); - BUG_ON(t == 0); - - - /* At this point, we received the gpadl created msg */ - *gpadl_handle = gpadlmsg->gpadl; - -cleanup: - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&msginfo->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - kfree(msginfo); - return ret; -} -EXPORT_SYMBOL_GPL(vmbus_establish_gpadl); - -/* - * vmbus_teardown_gpadl -Teardown the specified GPADL handle - */ -int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) -{ - struct vmbus_channel_gpadl_teardown *msg; - struct vmbus_channel_msginfo *info; - unsigned long flags; - int ret, t; - - info = kmalloc(sizeof(*info) + - sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); - if (!info) - return -ENOMEM; - - init_completion(&info->waitevent); - - msg = (struct vmbus_channel_gpadl_teardown *)info->msg; - - msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN; - msg->child_relid = channel->offermsg.child_relid; - msg->gpadl = gpadl_handle; - - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_add_tail(&info->msglistentry, - &vmbus_connection.chn_msg_list); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - ret = vmbus_post_msg(msg, - sizeof(struct vmbus_channel_gpadl_teardown)); - - BUG_ON(ret != 0); - t = wait_for_completion_timeout(&info->waitevent, 5*HZ); - BUG_ON(t == 0); - - /* Received a torndown response */ - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&info->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - kfree(info); - return ret; -} -EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); - -/* - * vmbus_close - Close the specified channel - */ -void vmbus_close(struct vmbus_channel *channel) -{ - struct vmbus_channel_close_channel *msg; - int ret; - unsigned long flags; - - /* Stop callback and cancel the timer asap */ - spin_lock_irqsave(&channel->inbound_lock, flags); - channel->onchannel_callback = NULL; - spin_unlock_irqrestore(&channel->inbound_lock, flags); - - /* Send a closing message */ - - msg = &channel->close_msg.msg; - - msg->header.msgtype = CHANNELMSG_CLOSECHANNEL; - msg->child_relid = channel->offermsg.child_relid; - - ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel)); - - BUG_ON(ret != 0); - /* Tear down the gpadl for the channel's ring buffer */ - if (channel->ringbuffer_gpadlhandle) - vmbus_teardown_gpadl(channel, - channel->ringbuffer_gpadlhandle); - - /* Cleanup the ring buffers for this channel */ - hv_ringbuffer_cleanup(&channel->outbound); - hv_ringbuffer_cleanup(&channel->inbound); - - free_pages((unsigned long)channel->ringbuffer_pages, - get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); - - -} -EXPORT_SYMBOL_GPL(vmbus_close); - -/** - * vmbus_sendpacket() - Send the specified buffer on the given channel - * @channel: Pointer to vmbus_channel structure. - * @buffer: Pointer to the buffer you want to receive the data into. - * @bufferlen: Maximum size of what the the buffer will hold - * @requestid: Identifier of the request - * @type: Type of packet that is being send e.g. negotiate, time - * packet etc. - * - * Sends data in @buffer directly to hyper-v via the vmbus - * This will send the data unparsed to hyper-v. - * - * Mainly used by Hyper-V drivers. - */ -int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer, - u32 bufferlen, u64 requestid, - enum vmbus_packet_type type, u32 flags) -{ - struct vmpacket_descriptor desc; - u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen; - u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64)); - struct scatterlist bufferlist[3]; - u64 aligned_data = 0; - int ret; - - - /* Setup the descriptor */ - desc.type = type; /* VmbusPacketTypeDataInBand; */ - desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */ - /* in 8-bytes granularity */ - desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3; - desc.len8 = (u16)(packetlen_aligned >> 3); - desc.trans_id = requestid; - - sg_init_table(bufferlist, 3); - sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor)); - sg_set_buf(&bufferlist[1], buffer, bufferlen); - sg_set_buf(&bufferlist[2], &aligned_data, - packetlen_aligned - packetlen); - - ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3); - - if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound)) - vmbus_setevent(channel); - - return ret; -} -EXPORT_SYMBOL(vmbus_sendpacket); - -/* - * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer - * packets using a GPADL Direct packet type. - */ -int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, - struct hv_page_buffer pagebuffers[], - u32 pagecount, void *buffer, u32 bufferlen, - u64 requestid) -{ - int ret; - int i; - struct vmbus_channel_packet_page_buffer desc; - u32 descsize; - u32 packetlen; - u32 packetlen_aligned; - struct scatterlist bufferlist[3]; - u64 aligned_data = 0; - - if (pagecount > MAX_PAGE_BUFFER_COUNT) - return -EINVAL; - - - /* - * Adjust the size down since vmbus_channel_packet_page_buffer is the - * largest size we support - */ - descsize = sizeof(struct vmbus_channel_packet_page_buffer) - - ((MAX_PAGE_BUFFER_COUNT - pagecount) * - sizeof(struct hv_page_buffer)); - packetlen = descsize + bufferlen; - packetlen_aligned = ALIGN(packetlen, sizeof(u64)); - - /* Setup the descriptor */ - desc.type = VM_PKT_DATA_USING_GPA_DIRECT; - desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; - desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */ - desc.length8 = (u16)(packetlen_aligned >> 3); - desc.transactionid = requestid; - desc.rangecount = pagecount; - - for (i = 0; i < pagecount; i++) { - desc.range[i].len = pagebuffers[i].len; - desc.range[i].offset = pagebuffers[i].offset; - desc.range[i].pfn = pagebuffers[i].pfn; - } - - sg_init_table(bufferlist, 3); - sg_set_buf(&bufferlist[0], &desc, descsize); - sg_set_buf(&bufferlist[1], buffer, bufferlen); - sg_set_buf(&bufferlist[2], &aligned_data, - packetlen_aligned - packetlen); - - ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3); - - if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound)) - vmbus_setevent(channel); - - return ret; -} -EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer); - -/* - * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet - * using a GPADL Direct packet type. - */ -int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, - struct hv_multipage_buffer *multi_pagebuffer, - void *buffer, u32 bufferlen, u64 requestid) -{ - int ret; - struct vmbus_channel_packet_multipage_buffer desc; - u32 descsize; - u32 packetlen; - u32 packetlen_aligned; - struct scatterlist bufferlist[3]; - u64 aligned_data = 0; - u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset, - multi_pagebuffer->len); - - - if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)) - return -EINVAL; - - /* - * Adjust the size down since vmbus_channel_packet_multipage_buffer is - * the largest size we support - */ - descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) - - ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) * - sizeof(u64)); - packetlen = descsize + bufferlen; - packetlen_aligned = ALIGN(packetlen, sizeof(u64)); - - - /* Setup the descriptor */ - desc.type = VM_PKT_DATA_USING_GPA_DIRECT; - desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; - desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */ - desc.length8 = (u16)(packetlen_aligned >> 3); - desc.transactionid = requestid; - desc.rangecount = 1; - - desc.range.len = multi_pagebuffer->len; - desc.range.offset = multi_pagebuffer->offset; - - memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array, - pfncount * sizeof(u64)); - - sg_init_table(bufferlist, 3); - sg_set_buf(&bufferlist[0], &desc, descsize); - sg_set_buf(&bufferlist[1], buffer, bufferlen); - sg_set_buf(&bufferlist[2], &aligned_data, - packetlen_aligned - packetlen); - - ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3); - - if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound)) - vmbus_setevent(channel); - - return ret; -} -EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer); - -/** - * vmbus_recvpacket() - Retrieve the user packet on the specified channel - * @channel: Pointer to vmbus_channel structure. - * @buffer: Pointer to the buffer you want to receive the data into. - * @bufferlen: Maximum size of what the the buffer will hold - * @buffer_actual_len: The actual size of the data after it was received - * @requestid: Identifier of the request - * - * Receives directly from the hyper-v vmbus and puts the data it received - * into Buffer. This will receive the data unparsed from hyper-v. - * - * Mainly used by Hyper-V drivers. - */ -int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, - u32 bufferlen, u32 *buffer_actual_len, u64 *requestid) -{ - struct vmpacket_descriptor desc; - u32 packetlen; - u32 userlen; - int ret; - - *buffer_actual_len = 0; - *requestid = 0; - - - ret = hv_ringbuffer_peek(&channel->inbound, &desc, - sizeof(struct vmpacket_descriptor)); - if (ret != 0) - return 0; - - packetlen = desc.len8 << 3; - userlen = packetlen - (desc.offset8 << 3); - - *buffer_actual_len = userlen; - - if (userlen > bufferlen) { - - pr_err("Buffer too small - got %d needs %d\n", - bufferlen, userlen); - return -ETOOSMALL; - } - - *requestid = desc.trans_id; - - /* Copy over the packet to the user buffer */ - ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen, - (desc.offset8 << 3)); - - - return 0; -} -EXPORT_SYMBOL(vmbus_recvpacket); - -/* - * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel - */ -int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, - u32 bufferlen, u32 *buffer_actual_len, - u64 *requestid) -{ - struct vmpacket_descriptor desc; - u32 packetlen; - u32 userlen; - int ret; - - *buffer_actual_len = 0; - *requestid = 0; - - - ret = hv_ringbuffer_peek(&channel->inbound, &desc, - sizeof(struct vmpacket_descriptor)); - if (ret != 0) - return 0; - - - packetlen = desc.len8 << 3; - userlen = packetlen - (desc.offset8 << 3); - - *buffer_actual_len = packetlen; - - if (packetlen > bufferlen) { - pr_err("Buffer too small - needed %d bytes but " - "got space for only %d bytes\n", - packetlen, bufferlen); - return -ENOBUFS; - } - - *requestid = desc.trans_id; - - /* Copy over the entire packet to the user buffer */ - ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0); - - return 0; -} -EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c deleted file mode 100644 index 9f00752..0000000 --- a/drivers/staging/hv/channel_mgmt.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - -struct vmbus_channel_message_table_entry { - enum vmbus_channel_message_type message_type; - void (*message_handler)(struct vmbus_channel_message_header *msg); -}; - -#define MAX_MSG_TYPES 4 -#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 - -static const uuid_le - supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { - /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ - /* Storage - SCSI */ - { - .b = { - 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f - } - }, - - /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ - /* Network */ - { - .b = { - 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E - } - }, - - /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ - /* Input */ - { - .b = { - 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, - 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A - } - }, - - /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ - /* IDE */ - { - .b = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } - }, - /* 0E0B6031-5213-4934-818B-38D90CED39DB */ - /* Shutdown */ - { - .b = { - 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB - } - }, - /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ - /* TimeSync */ - { - .b = { - 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf - } - }, - /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ - /* Heartbeat */ - { - .b = { - 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d - } - }, - /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ - /* KVP */ - { - .b = { - 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 - } - }, - -}; - - -/** - * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message - * @icmsghdrp: Pointer to msg header structure - * @icmsg_negotiate: Pointer to negotiate message structure - * @buf: Raw buffer channel data - * - * @icmsghdrp is of type &struct icmsg_hdr. - * @negop is of type &struct icmsg_negotiate. - * Set up and fill in default negotiate response message. This response can - * come from both the vmbus driver and the hv_utils driver. The current api - * will respond properly to both Windows 2008 and Windows 2008-R2 operating - * systems. - * - * Mainly used by Hyper-V drivers. - */ -void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, - struct icmsg_negotiate *negop, - u8 *buf) -{ - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - icmsghdrp->icmsgsize = 0x10; - - negop = (struct icmsg_negotiate *)&buf[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - if (negop->icframe_vercnt == 2 && - negop->icversion_data[1].major == 3) { - negop->icversion_data[0].major = 3; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 3; - negop->icversion_data[1].minor = 0; - } else { - negop->icversion_data[0].major = 1; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 1; - negop->icversion_data[1].minor = 0; - } - - negop->icframe_vercnt = 1; - negop->icmsg_vercnt = 1; - } -} -EXPORT_SYMBOL(prep_negotiate_resp); - -/* - * alloc_channel - Allocate and initialize a vmbus channel object - */ -static struct vmbus_channel *alloc_channel(void) -{ - struct vmbus_channel *channel; - - channel = kzalloc(sizeof(*channel), GFP_ATOMIC); - if (!channel) - return NULL; - - spin_lock_init(&channel->inbound_lock); - - channel->controlwq = create_workqueue("hv_vmbus_ctl"); - if (!channel->controlwq) { - kfree(channel); - return NULL; - } - - return channel; -} - -/* - * release_hannel - Release the vmbus channel object itself - */ -static void release_channel(struct work_struct *work) -{ - struct vmbus_channel *channel = container_of(work, - struct vmbus_channel, - work); - - destroy_workqueue(channel->controlwq); - - kfree(channel); -} - -/* - * free_channel - Release the resources used by the vmbus channel object - */ -void free_channel(struct vmbus_channel *channel) -{ - - /* - * We have to release the channel's workqueue/thread in the vmbus's - * workqueue/thread context - * ie we can't destroy ourselves. - */ - INIT_WORK(&channel->work, release_channel); - queue_work(vmbus_connection.work_queue, &channel->work); -} - - - -/* - * vmbus_process_rescind_offer - - * Rescind the offer by initiating a device removal - */ -static void vmbus_process_rescind_offer(struct work_struct *work) -{ - struct vmbus_channel *channel = container_of(work, - struct vmbus_channel, - work); - - vmbus_device_unregister(channel->device_obj); -} - -/* - * vmbus_process_offer - Process the offer by creating a channel/device - * associated with this offer - */ -static void vmbus_process_offer(struct work_struct *work) -{ - struct vmbus_channel *newchannel = container_of(work, - struct vmbus_channel, - work); - struct vmbus_channel *channel; - bool fnew = true; - int ret; - unsigned long flags; - - /* The next possible work is rescind handling */ - INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); - - /* Make sure this is a new offer */ - spin_lock_irqsave(&vmbus_connection.channel_lock, flags); - - list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { - if (!uuid_le_cmp(channel->offermsg.offer.if_type, - newchannel->offermsg.offer.if_type) && - !uuid_le_cmp(channel->offermsg.offer.if_instance, - newchannel->offermsg.offer.if_instance)) { - fnew = false; - break; - } - } - - if (fnew) - list_add_tail(&newchannel->listentry, - &vmbus_connection.chn_list); - - spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); - - if (!fnew) { - free_channel(newchannel); - return; - } - - /* - * Start the process of binding this offer to the driver - * We need to set the DeviceObject field before calling - * vmbus_child_dev_add() - */ - newchannel->device_obj = vmbus_device_create( - &newchannel->offermsg.offer.if_type, - &newchannel->offermsg.offer.if_instance, - newchannel); - - /* - * Add the new device to the bus. This will kick off device-driver - * binding which eventually invokes the device driver's AddDevice() - * method. - */ - ret = vmbus_device_register(newchannel->device_obj); - if (ret != 0) { - pr_err("unable to add child device object (relid %d)\n", - newchannel->offermsg.child_relid); - - spin_lock_irqsave(&vmbus_connection.channel_lock, flags); - list_del(&newchannel->listentry); - spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); - - free_channel(newchannel); - } else { - /* - * This state is used to indicate a successful open - * so that when we do close the channel normally, we - * can cleanup properly - */ - newchannel->state = CHANNEL_OPEN_STATE; - } -} - -/* - * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. - * - */ -static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_offer_channel *offer; - struct vmbus_channel *newchannel; - uuid_le *guidtype; - uuid_le *guidinstance; - int i; - int fsupported = 0; - - offer = (struct vmbus_channel_offer_channel *)hdr; - for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { - if (!uuid_le_cmp(offer->offer.if_type, - supported_device_classes[i])) { - fsupported = 1; - break; - } - } - - if (!fsupported) - return; - - guidtype = &offer->offer.if_type; - guidinstance = &offer->offer.if_instance; - - /* Allocate the channel object and save this offer. */ - newchannel = alloc_channel(); - if (!newchannel) { - pr_err("Unable to allocate channel object\n"); - return; - } - - memcpy(&newchannel->offermsg, offer, - sizeof(struct vmbus_channel_offer_channel)); - newchannel->monitor_grp = (u8)offer->monitorid / 32; - newchannel->monitor_bit = (u8)offer->monitorid % 32; - - INIT_WORK(&newchannel->work, vmbus_process_offer); - queue_work(newchannel->controlwq, &newchannel->work); -} - -/* - * vmbus_onoffer_rescind - Rescind offer handler. - * - * We queue a work item to process this offer synchronously - */ -static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_rescind_offer *rescind; - struct vmbus_channel *channel; - - rescind = (struct vmbus_channel_rescind_offer *)hdr; - channel = relid2channel(rescind->child_relid); - - if (channel == NULL) - /* Just return here, no channel found */ - return; - - /* work is initialized for vmbus_process_rescind_offer() from - * vmbus_process_offer() where the channel got created */ - queue_work(channel->controlwq, &channel->work); -} - -/* - * vmbus_onoffers_delivered - - * This is invoked when all offers have been delivered. - * - * Nothing to do here. - */ -static void vmbus_onoffers_delivered( - struct vmbus_channel_message_header *hdr) -{ -} - -/* - * vmbus_onopen_result - Open result handler. - * - * This is invoked when we received a response to our channel open request. - * Find the matching request, copy the response and signal the requesting - * thread. - */ -static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_open_result *result; - struct vmbus_channel_msginfo *msginfo; - struct vmbus_channel_message_header *requestheader; - struct vmbus_channel_open_channel *openmsg; - unsigned long flags; - - result = (struct vmbus_channel_open_result *)hdr; - - /* - * Find the open msg, copy the result and signal/unblock the wait event - */ - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - - list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, - msglistentry) { - requestheader = - (struct vmbus_channel_message_header *)msginfo->msg; - - if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) { - openmsg = - (struct vmbus_channel_open_channel *)msginfo->msg; - if (openmsg->child_relid == result->child_relid && - openmsg->openid == result->openid) { - memcpy(&msginfo->response.open_result, - result, - sizeof( - struct vmbus_channel_open_result)); - complete(&msginfo->waitevent); - break; - } - } - } - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); -} - -/* - * vmbus_ongpadl_created - GPADL created handler. - * - * This is invoked when we received a response to our gpadl create request. - * Find the matching request, copy the response and signal the requesting - * thread. - */ -static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_gpadl_created *gpadlcreated; - struct vmbus_channel_msginfo *msginfo; - struct vmbus_channel_message_header *requestheader; - struct vmbus_channel_gpadl_header *gpadlheader; - unsigned long flags; - - gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; - - /* - * Find the establish msg, copy the result and signal/unblock the wait - * event - */ - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - - list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, - msglistentry) { - requestheader = - (struct vmbus_channel_message_header *)msginfo->msg; - - if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) { - gpadlheader = - (struct vmbus_channel_gpadl_header *)requestheader; - - if ((gpadlcreated->child_relid == - gpadlheader->child_relid) && - (gpadlcreated->gpadl == gpadlheader->gpadl)) { - memcpy(&msginfo->response.gpadl_created, - gpadlcreated, - sizeof( - struct vmbus_channel_gpadl_created)); - complete(&msginfo->waitevent); - break; - } - } - } - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); -} - -/* - * vmbus_ongpadl_torndown - GPADL torndown handler. - * - * This is invoked when we received a response to our gpadl teardown request. - * Find the matching request, copy the response and signal the requesting - * thread. - */ -static void vmbus_ongpadl_torndown( - struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_gpadl_torndown *gpadl_torndown; - struct vmbus_channel_msginfo *msginfo; - struct vmbus_channel_message_header *requestheader; - struct vmbus_channel_gpadl_teardown *gpadl_teardown; - unsigned long flags; - - gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; - - /* - * Find the open msg, copy the result and signal/unblock the wait event - */ - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - - list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, - msglistentry) { - requestheader = - (struct vmbus_channel_message_header *)msginfo->msg; - - if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) { - gpadl_teardown = - (struct vmbus_channel_gpadl_teardown *)requestheader; - - if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) { - memcpy(&msginfo->response.gpadl_torndown, - gpadl_torndown, - sizeof( - struct vmbus_channel_gpadl_torndown)); - complete(&msginfo->waitevent); - break; - } - } - } - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); -} - -/* - * vmbus_onversion_response - Version response handler - * - * This is invoked when we received a response to our initiate contact request. - * Find the matching request, copy the response and signal the requesting - * thread. - */ -static void vmbus_onversion_response( - struct vmbus_channel_message_header *hdr) -{ - struct vmbus_channel_msginfo *msginfo; - struct vmbus_channel_message_header *requestheader; - struct vmbus_channel_initiate_contact *initiate; - struct vmbus_channel_version_response *version_response; - unsigned long flags; - - version_response = (struct vmbus_channel_version_response *)hdr; - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - - list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, - msglistentry) { - requestheader = - (struct vmbus_channel_message_header *)msginfo->msg; - - if (requestheader->msgtype == - CHANNELMSG_INITIATE_CONTACT) { - initiate = - (struct vmbus_channel_initiate_contact *)requestheader; - memcpy(&msginfo->response.version_response, - version_response, - sizeof(struct vmbus_channel_version_response)); - complete(&msginfo->waitevent); - } - } - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); -} - -/* Channel message dispatch table */ -static struct vmbus_channel_message_table_entry - channel_message_table[CHANNELMSG_COUNT] = { - {CHANNELMSG_INVALID, NULL}, - {CHANNELMSG_OFFERCHANNEL, vmbus_onoffer}, - {CHANNELMSG_RESCIND_CHANNELOFFER, vmbus_onoffer_rescind}, - {CHANNELMSG_REQUESTOFFERS, NULL}, - {CHANNELMSG_ALLOFFERS_DELIVERED, vmbus_onoffers_delivered}, - {CHANNELMSG_OPENCHANNEL, NULL}, - {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result}, - {CHANNELMSG_CLOSECHANNEL, NULL}, - {CHANNELMSG_GPADL_HEADER, NULL}, - {CHANNELMSG_GPADL_BODY, NULL}, - {CHANNELMSG_GPADL_CREATED, vmbus_ongpadl_created}, - {CHANNELMSG_GPADL_TEARDOWN, NULL}, - {CHANNELMSG_GPADL_TORNDOWN, vmbus_ongpadl_torndown}, - {CHANNELMSG_RELID_RELEASED, NULL}, - {CHANNELMSG_INITIATE_CONTACT, NULL}, - {CHANNELMSG_VERSION_RESPONSE, vmbus_onversion_response}, - {CHANNELMSG_UNLOAD, NULL}, -}; - -/* - * vmbus_onmessage - Handler for channel protocol messages. - * - * This is invoked in the vmbus worker thread context. - */ -void vmbus_onmessage(void *context) -{ - struct hv_message *msg = context; - struct vmbus_channel_message_header *hdr; - int size; - - hdr = (struct vmbus_channel_message_header *)msg->u.payload; - size = msg->header.payload_size; - - if (hdr->msgtype >= CHANNELMSG_COUNT) { - pr_err("Received invalid channel message type %d size %d\n", - hdr->msgtype, size); - print_hex_dump_bytes("", DUMP_PREFIX_NONE, - (unsigned char *)msg->u.payload, size); - return; - } - - if (channel_message_table[hdr->msgtype].message_handler) - channel_message_table[hdr->msgtype].message_handler(hdr); - else - pr_err("Unhandled channel message type %d\n", hdr->msgtype); -} - -/* - * vmbus_request_offers - Send a request to get all our pending offers. - */ -int vmbus_request_offers(void) -{ - struct vmbus_channel_message_header *msg; - struct vmbus_channel_msginfo *msginfo; - int ret, t; - - msginfo = kmalloc(sizeof(*msginfo) + - sizeof(struct vmbus_channel_message_header), - GFP_KERNEL); - if (!msginfo) - return -ENOMEM; - - init_completion(&msginfo->waitevent); - - msg = (struct vmbus_channel_message_header *)msginfo->msg; - - msg->msgtype = CHANNELMSG_REQUESTOFFERS; - - - ret = vmbus_post_msg(msg, - sizeof(struct vmbus_channel_message_header)); - if (ret != 0) { - pr_err("Unable to request offers - %d\n", ret); - - goto cleanup; - } - - t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - - -cleanup: - kfree(msginfo); - - return ret; -} - -/* eof */ diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c deleted file mode 100644 index 649b91b..0000000 --- a/drivers/staging/hv/connection.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - - -struct vmbus_connection vmbus_connection = { - .conn_state = DISCONNECTED, - .next_gpadl_handle = ATOMIC_INIT(0xE1E10), -}; - -/* - * vmbus_connect - Sends a connect request on the partition service connection - */ -int vmbus_connect(void) -{ - int ret = 0; - int t; - struct vmbus_channel_msginfo *msginfo = NULL; - struct vmbus_channel_initiate_contact *msg; - unsigned long flags; - - /* Initialize the vmbus connection */ - vmbus_connection.conn_state = CONNECTING; - vmbus_connection.work_queue = create_workqueue("hv_vmbus_con"); - if (!vmbus_connection.work_queue) { - ret = -ENOMEM; - goto cleanup; - } - - INIT_LIST_HEAD(&vmbus_connection.chn_msg_list); - spin_lock_init(&vmbus_connection.channelmsg_lock); - - INIT_LIST_HEAD(&vmbus_connection.chn_list); - spin_lock_init(&vmbus_connection.channel_lock); - - /* - * Setup the vmbus event connection for channel interrupt - * abstraction stuff - */ - vmbus_connection.int_page = - (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0); - if (vmbus_connection.int_page == NULL) { - ret = -ENOMEM; - goto cleanup; - } - - vmbus_connection.recv_int_page = vmbus_connection.int_page; - vmbus_connection.send_int_page = - (void *)((unsigned long)vmbus_connection.int_page + - (PAGE_SIZE >> 1)); - - /* - * Setup the monitor notification facility. The 1st page for - * parent->child and the 2nd page for child->parent - */ - vmbus_connection.monitor_pages = - (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1); - if (vmbus_connection.monitor_pages == NULL) { - ret = -ENOMEM; - goto cleanup; - } - - msginfo = kzalloc(sizeof(*msginfo) + - sizeof(struct vmbus_channel_initiate_contact), - GFP_KERNEL); - if (msginfo == NULL) { - ret = -ENOMEM; - goto cleanup; - } - - init_completion(&msginfo->waitevent); - - msg = (struct vmbus_channel_initiate_contact *)msginfo->msg; - - msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT; - msg->vmbus_version_requested = VMBUS_REVISION_NUMBER; - msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); - msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages); - msg->monitor_page2 = virt_to_phys( - (void *)((unsigned long)vmbus_connection.monitor_pages + - PAGE_SIZE)); - - /* - * Add to list before we send the request since we may - * receive the response before returning from this routine - */ - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_add_tail(&msginfo->msglistentry, - &vmbus_connection.chn_msg_list); - - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - ret = vmbus_post_msg(msg, - sizeof(struct vmbus_channel_initiate_contact)); - if (ret != 0) { - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&msginfo->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, - flags); - goto cleanup; - } - - /* Wait for the connection response */ - t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); - if (t == 0) { - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, - flags); - list_del(&msginfo->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, - flags); - ret = -ETIMEDOUT; - goto cleanup; - } - - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - list_del(&msginfo->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - - /* Check if successful */ - if (msginfo->response.version_response.version_supported) { - vmbus_connection.conn_state = CONNECTED; - } else { - pr_err("Unable to connect, " - "Version %d not supported by Hyper-V\n", - VMBUS_REVISION_NUMBER); - ret = -ECONNREFUSED; - goto cleanup; - } - - kfree(msginfo); - return 0; - -cleanup: - vmbus_connection.conn_state = DISCONNECTED; - - if (vmbus_connection.work_queue) - destroy_workqueue(vmbus_connection.work_queue); - - if (vmbus_connection.int_page) { - free_pages((unsigned long)vmbus_connection.int_page, 0); - vmbus_connection.int_page = NULL; - } - - if (vmbus_connection.monitor_pages) { - free_pages((unsigned long)vmbus_connection.monitor_pages, 1); - vmbus_connection.monitor_pages = NULL; - } - - kfree(msginfo); - - return ret; -} - - -/* - * relid2channel - Get the channel object given its - * child relative id (ie channel id) - */ -struct vmbus_channel *relid2channel(u32 relid) -{ - struct vmbus_channel *channel; - struct vmbus_channel *found_channel = NULL; - unsigned long flags; - - spin_lock_irqsave(&vmbus_connection.channel_lock, flags); - list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { - if (channel->offermsg.child_relid == relid) { - found_channel = channel; - break; - } - } - spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); - - return found_channel; -} - -/* - * process_chn_event - Process a channel event notification - */ -static void process_chn_event(u32 relid) -{ - struct vmbus_channel *channel; - unsigned long flags; - - /* - * Find the channel based on this relid and invokes the - * channel callback to process the event - */ - channel = relid2channel(relid); - - if (!channel) { - pr_err("channel not found for relid - %u\n", relid); - return; - } - - /* - * A channel once created is persistent even when there - * is no driver handling the device. An unloading driver - * sets the onchannel_callback to NULL under the - * protection of the channel inbound_lock. Thus, checking - * and invoking the driver specific callback takes care of - * orderly unloading of the driver. - */ - - spin_lock_irqsave(&channel->inbound_lock, flags); - if (channel->onchannel_callback != NULL) - channel->onchannel_callback(channel->channel_callback_context); - else - pr_err("no channel callback for relid - %u\n", relid); - - spin_unlock_irqrestore(&channel->inbound_lock, flags); -} - -/* - * vmbus_on_event - Handler for events - */ -void vmbus_on_event(unsigned long data) -{ - u32 dword; - u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; - int bit; - u32 relid; - u32 *recv_int_page = vmbus_connection.recv_int_page; - - /* Check events */ - if (!recv_int_page) - return; - for (dword = 0; dword < maxdword; dword++) { - if (!recv_int_page[dword]) - continue; - for (bit = 0; bit < 32; bit++) { - if (sync_test_and_clear_bit(bit, - (unsigned long *)&recv_int_page[dword])) { - relid = (dword << 5) + bit; - - if (relid == 0) - /* - * Special case - vmbus - * channel protocol msg - */ - continue; - - process_chn_event(relid); - } - } - } -} - -/* - * vmbus_post_msg - Send a msg on the vmbus's message connection - */ -int vmbus_post_msg(void *buffer, size_t buflen) -{ - union hv_connection_id conn_id; - int ret = 0; - int retries = 0; - - conn_id.asu32 = 0; - conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; - - /* - * hv_post_message() can have transient failures because of - * insufficient resources. Retry the operation a couple of - * times before giving up. - */ - while (retries < 3) { - ret = hv_post_message(conn_id, 1, buffer, buflen); - if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) - return ret; - retries++; - msleep(100); - } - return ret; -} - -/* - * vmbus_set_event - Send an event notification to the parent - */ -int vmbus_set_event(u32 child_relid) -{ - /* Each u32 represents 32 channels */ - sync_set_bit(child_relid & 31, - (unsigned long *)vmbus_connection.send_int_page + - (child_relid >> 5)); - - return hv_signal_event(); -} diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c deleted file mode 100644 index 06f1e15..0000000 --- a/drivers/staging/hv/hv.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - -/* The one and only */ -struct hv_context hv_context = { - .synic_initialized = false, - .hypercall_page = NULL, - .signal_event_param = NULL, - .signal_event_buffer = NULL, -}; - -/* - * query_hypervisor_presence - * - Query the cpuid for presence of windows hypervisor - */ -static int query_hypervisor_presence(void) -{ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - unsigned int op; - - eax = 0; - ebx = 0; - ecx = 0; - edx = 0; - op = HVCPUID_VERSION_FEATURES; - cpuid(op, &eax, &ebx, &ecx, &edx); - - return ecx & HV_PRESENT_BIT; -} - -/* - * query_hypervisor_info - Get version info of the windows hypervisor - */ -static int query_hypervisor_info(void) -{ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - unsigned int max_leaf; - unsigned int op; - - /* - * Its assumed that this is called after confirming that Viridian - * is present. Query id and revision. - */ - eax = 0; - ebx = 0; - ecx = 0; - edx = 0; - op = HVCPUID_VENDOR_MAXFUNCTION; - cpuid(op, &eax, &ebx, &ecx, &edx); - - max_leaf = eax; - - if (max_leaf >= HVCPUID_VERSION) { - eax = 0; - ebx = 0; - ecx = 0; - edx = 0; - op = HVCPUID_VERSION; - cpuid(op, &eax, &ebx, &ecx, &edx); - pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n", - eax, - ebx >> 16, - ebx & 0xFFFF, - ecx, - edx >> 24, - edx & 0xFFFFFF); - } - return max_leaf; -} - -/* - * do_hypercall- Invoke the specified hypercall - */ -static u64 do_hypercall(u64 control, void *input, void *output) -{ -#ifdef CONFIG_X86_64 - u64 hv_status = 0; - u64 input_address = (input) ? virt_to_phys(input) : 0; - u64 output_address = (output) ? virt_to_phys(output) : 0; - void *hypercall_page = hv_context.hypercall_page; - - __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); - __asm__ __volatile__("call *%3" : "=a" (hv_status) : - "c" (control), "d" (input_address), - "m" (hypercall_page)); - - return hv_status; - -#else - - u32 control_hi = control >> 32; - u32 control_lo = control & 0xFFFFFFFF; - u32 hv_status_hi = 1; - u32 hv_status_lo = 1; - u64 input_address = (input) ? virt_to_phys(input) : 0; - u32 input_address_hi = input_address >> 32; - u32 input_address_lo = input_address & 0xFFFFFFFF; - u64 output_address = (output) ? virt_to_phys(output) : 0; - u32 output_address_hi = output_address >> 32; - u32 output_address_lo = output_address & 0xFFFFFFFF; - void *hypercall_page = hv_context.hypercall_page; - - __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), - "=a"(hv_status_lo) : "d" (control_hi), - "a" (control_lo), "b" (input_address_hi), - "c" (input_address_lo), "D"(output_address_hi), - "S"(output_address_lo), "m" (hypercall_page)); - - return hv_status_lo | ((u64)hv_status_hi << 32); -#endif /* !x86_64 */ -} - -/* - * hv_init - Main initialization routine. - * - * This routine must be called before any other routines in here are called - */ -int hv_init(void) -{ - int max_leaf; - union hv_x64_msr_hypercall_contents hypercall_msr; - void *virtaddr = NULL; - - memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); - memset(hv_context.synic_message_page, 0, - sizeof(void *) * MAX_NUM_CPUS); - - if (!query_hypervisor_presence()) - goto cleanup; - - 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; - - /* See if the hypercall page is already set */ - rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - - virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); - - if (!virtaddr) - goto cleanup; - - hypercall_msr.enable = 1; - - hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr); - wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - - /* Confirm that hypercall page did get setup. */ - hypercall_msr.as_uint64 = 0; - rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - - if (!hypercall_msr.enable) - goto cleanup; - - hv_context.hypercall_page = virtaddr; - - /* Setup the global signal event param for the signal event hypercall */ - hv_context.signal_event_buffer = - kmalloc(sizeof(struct hv_input_signal_event_buffer), - GFP_KERNEL); - if (!hv_context.signal_event_buffer) - goto cleanup; - - hv_context.signal_event_param = - (struct hv_input_signal_event *) - (ALIGN((unsigned long) - hv_context.signal_event_buffer, - HV_HYPERCALL_PARAM_ALIGN)); - hv_context.signal_event_param->connectionid.asu32 = 0; - hv_context.signal_event_param->connectionid.u.id = - VMBUS_EVENT_CONNECTION_ID; - hv_context.signal_event_param->flag_number = 0; - hv_context.signal_event_param->rsvdz = 0; - - return 0; - -cleanup: - if (virtaddr) { - if (hypercall_msr.enable) { - hypercall_msr.as_uint64 = 0; - wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - } - - vfree(virtaddr); - } - - return -ENOTSUPP; -} - -/* - * hv_cleanup - Cleanup routine. - * - * This routine is called normally during driver unloading or exiting. - */ -void hv_cleanup(void) -{ - union hv_x64_msr_hypercall_contents hypercall_msr; - - kfree(hv_context.signal_event_buffer); - hv_context.signal_event_buffer = NULL; - hv_context.signal_event_param = NULL; - - if (hv_context.hypercall_page) { - hypercall_msr.as_uint64 = 0; - wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - vfree(hv_context.hypercall_page); - hv_context.hypercall_page = NULL; - } -} - -/* - * hv_post_message - Post a message using the hypervisor message IPC. - * - * This involves a hypercall. - */ -u16 hv_post_message(union hv_connection_id connection_id, - enum hv_message_type message_type, - void *payload, size_t payload_size) -{ - struct aligned_input { - u64 alignment8; - struct hv_input_post_message msg; - }; - - struct hv_input_post_message *aligned_msg; - u16 status; - unsigned long addr; - - if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) - return -EMSGSIZE; - - addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC); - if (!addr) - return -ENOMEM; - - aligned_msg = (struct hv_input_post_message *) - (ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN)); - - aligned_msg->connectionid = connection_id; - aligned_msg->message_type = message_type; - aligned_msg->payload_size = payload_size; - memcpy((void *)aligned_msg->payload, payload, payload_size); - - status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL) - & 0xFFFF; - - kfree((void *)addr); - - return status; -} - - -/* - * hv_signal_event - - * Signal an event on the specified connection using the hypervisor event IPC. - * - * This involves a hypercall. - */ -u16 hv_signal_event(void) -{ - u16 status; - - status = do_hypercall(HVCALL_SIGNAL_EVENT, - hv_context.signal_event_param, - NULL) & 0xFFFF; - return status; -} - -/* - * hv_synic_init - Initialize the Synthethic Interrupt Controller. - * - * If it is already initialized by another entity (ie x2v shim), we need to - * retrieve the initialized message and event pages. Otherwise, we create and - * initialize the message and event pages. - */ -void hv_synic_init(void *irqarg) -{ - u64 version; - union hv_synic_simp simp; - union hv_synic_siefp siefp; - union hv_synic_sint shared_sint; - union hv_synic_scontrol sctrl; - - u32 irq_vector = *((u32 *)(irqarg)); - int cpu = smp_processor_id(); - - if (!hv_context.hypercall_page) - return; - - /* Check the version */ - rdmsrl(HV_X64_MSR_SVERSION, version); - - hv_context.synic_message_page[cpu] = - (void *)get_zeroed_page(GFP_ATOMIC); - - if (hv_context.synic_message_page[cpu] == NULL) { - pr_err("Unable to allocate SYNIC message page\n"); - goto cleanup; - } - - hv_context.synic_event_page[cpu] = - (void *)get_zeroed_page(GFP_ATOMIC); - - if (hv_context.synic_event_page[cpu] == NULL) { - pr_err("Unable to allocate SYNIC event page\n"); - goto cleanup; - } - - /* Setup the Synic's message page */ - rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); - simp.simp_enabled = 1; - simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu]) - >> PAGE_SHIFT; - - wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); - - /* Setup the Synic's event page */ - rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); - siefp.siefp_enabled = 1; - siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu]) - >> PAGE_SHIFT; - - wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); - - /* Setup the shared SINT. */ - rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - - shared_sint.as_uint64 = 0; - shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ - shared_sint.masked = false; - shared_sint.auto_eoi = false; - - wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - - /* Enable the global synic bit */ - rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); - sctrl.enable = 1; - - wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); - - hv_context.synic_initialized = true; - return; - -cleanup: - if (hv_context.synic_event_page[cpu]) - free_page((unsigned long)hv_context.synic_event_page[cpu]); - - if (hv_context.synic_message_page[cpu]) - free_page((unsigned long)hv_context.synic_message_page[cpu]); - return; -} - -/* - * hv_synic_cleanup - Cleanup routine for hv_synic_init(). - */ -void hv_synic_cleanup(void *arg) -{ - union hv_synic_sint shared_sint; - union hv_synic_simp simp; - union hv_synic_siefp siefp; - int cpu = smp_processor_id(); - - if (!hv_context.synic_initialized) - return; - - rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - - shared_sint.masked = 1; - - /* Need to correctly cleanup in the case of SMP!!! */ - /* Disable the interrupt */ - wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - - rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); - simp.simp_enabled = 0; - simp.base_simp_gpa = 0; - - wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); - - rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); - siefp.siefp_enabled = 0; - siefp.base_siefp_gpa = 0; - - wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); - - free_page((unsigned long)hv_context.synic_message_page[cpu]); - free_page((unsigned long)hv_context.synic_event_page[cpu]); -} diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c deleted file mode 100644 index 1e9515c..0000000 --- a/drivers/staging/hv/hv_kvp.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * An implementation of key value pair (KVP) functionality for Linux. - * - * - * Copyright (C) 2010, Novell, Inc. - * Author : K. Y. Srinivasan - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -#include "hyperv.h" -#include "hv_kvp.h" - - - -/* - * Global state maintained for transaction that is being processed. - * Note that only one transaction can be active at any point in time. - * - * This state is set when we receive a request from the host; we - * cleanup this state when the transaction is completed - when we respond - * to the host with the key value. - */ - -static struct { - bool active; /* transaction status - active or not */ - int recv_len; /* number of bytes received. */ - int index; /* current index */ - struct vmbus_channel *recv_channel; /* chn we got the request */ - u64 recv_req_id; /* request ID. */ -} kvp_transaction; - -static void kvp_send_key(struct work_struct *dummy); - -#define TIMEOUT_FIRED 1 - -static void kvp_respond_to_host(char *key, char *value, int error); -static void kvp_work_func(struct work_struct *dummy); -static void kvp_register(void); - -static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); -static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); - -static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; -static const char kvp_name[] = "kvp_kernel_module"; -static u8 *recv_buffer; -/* - * Register the kernel component with the user-level daemon. - * As part of this registration, pass the LIC version number. - */ - -static void -kvp_register(void) -{ - - struct cn_msg *msg; - - msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC); - - if (msg) { - msg->id.idx = CN_KVP_IDX; - msg->id.val = CN_KVP_VAL; - msg->seq = KVP_REGISTER; - strcpy(msg->data, HV_DRV_VERSION); - msg->len = strlen(HV_DRV_VERSION) + 1; - cn_netlink_send(msg, 0, GFP_ATOMIC); - kfree(msg); - } -} -static void -kvp_work_func(struct work_struct *dummy) -{ - /* - * If the timer fires, the user-mode component has not responded; - * process the pending transaction. - */ - kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); -} - -/* - * Callback when data is received from user mode. - */ - -static void -kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) -{ - struct hv_ku_msg *message; - - message = (struct hv_ku_msg *)msg->data; - if (msg->seq == KVP_REGISTER) { - pr_info("KVP: user-mode registering done.\n"); - kvp_register(); - } - - if (msg->seq == KVP_USER_SET) { - /* - * Complete the transaction by forwarding the key value - * to the host. But first, cancel the timeout. - */ - if (cancel_delayed_work_sync(&kvp_work)) - kvp_respond_to_host(message->kvp_key, - message->kvp_value, - !strlen(message->kvp_key)); - } -} - -static void -kvp_send_key(struct work_struct *dummy) -{ - struct cn_msg *msg; - int index = kvp_transaction.index; - - msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); - - if (msg) { - msg->id.idx = CN_KVP_IDX; - msg->id.val = CN_KVP_VAL; - msg->seq = KVP_KERNEL_GET; - ((struct hv_ku_msg *)msg->data)->kvp_index = index; - msg->len = sizeof(struct hv_ku_msg); - cn_netlink_send(msg, 0, GFP_ATOMIC); - kfree(msg); - } - return; -} - -/* - * Send a response back to the host. - */ - -static void -kvp_respond_to_host(char *key, char *value, int error) -{ - struct hv_kvp_msg *kvp_msg; - struct hv_kvp_msg_enumerate *kvp_data; - char *key_name; - struct icmsg_hdr *icmsghdrp; - int keylen, valuelen; - u32 buf_len; - struct vmbus_channel *channel; - u64 req_id; - - /* - * If a transaction is not active; log and return. - */ - - if (!kvp_transaction.active) { - /* - * This is a spurious call! - */ - pr_warn("KVP: Transaction not active\n"); - return; - } - /* - * Copy the global state for completing the transaction. Note that - * only one transaction can be active at a time. - */ - - buf_len = kvp_transaction.recv_len; - channel = kvp_transaction.recv_channel; - req_id = kvp_transaction.recv_req_id; - - kvp_transaction.active = false; - - if (channel->onchannel_callback == NULL) - /* - * We have raced with util driver being unloaded; - * silently return. - */ - return; - - icmsghdrp = (struct icmsg_hdr *) - &recv_buffer[sizeof(struct vmbuspipe_hdr)]; - kvp_msg = (struct hv_kvp_msg *) - &recv_buffer[sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - kvp_data = &kvp_msg->kvp_data; - key_name = key; - - /* - * If the error parameter is set, terminate the host's enumeration. - */ - if (error) { - /* - * We don't support this index or the we have timedout; - * terminate the host-side iteration by returning an error. - */ - icmsghdrp->status = HV_E_FAIL; - goto response_done; - } - - /* - * 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); - kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ - valuelen = utf8s_to_utf16s(value, strlen(value), - (wchar_t *)kvp_data->data.value); - kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ - - kvp_data->data.value_type = REG_SZ; /* all our values are strings */ - icmsghdrp->status = HV_S_OK; - -response_done: - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, - VM_PKT_DATA_INBAND, 0); - -} - -/* - * This callback is invoked when we get a KVP message from the host. - * The host ensures that only one KVP transaction can be active at a time. - * KVP implementation in Linux needs to forward the key to a user-mde - * component to retrive the corresponding value. Consequently, we cannot - * respond to the host in the conext of this callback. Since the host - * guarantees that at most only one transaction can be active at a time, - * we stash away the transaction state in a set of global variables. - */ - -void hv_kvp_onchannelcallback(void *context) -{ - struct vmbus_channel *channel = context; - u32 recvlen; - u64 requestid; - - struct hv_kvp_msg *kvp_msg; - struct hv_kvp_msg_enumerate *kvp_data; - - struct icmsg_hdr *icmsghdrp; - struct icmsg_negotiate *negop = NULL; - - - vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); - - if (recvlen > 0) { - icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ - sizeof(struct vmbuspipe_hdr)]; - - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - prep_negotiate_resp(icmsghdrp, negop, recv_buffer); - } else { - kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - kvp_data = &kvp_msg->kvp_data; - - /* - * We only support the "get" operation on - * "KVP_POOL_AUTO" pool. - */ - - if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) || - (kvp_msg->kvp_hdr.operation != - KVP_OP_ENUMERATE)) { - icmsghdrp->status = HV_E_FAIL; - goto callback_done; - } - - /* - * Stash away this global state for completing the - * transaction; note transactions are serialized. - */ - kvp_transaction.recv_len = recvlen; - kvp_transaction.recv_channel = channel; - kvp_transaction.recv_req_id = requestid; - kvp_transaction.active = true; - kvp_transaction.index = kvp_data->index; - - /* - * Get the information from the - * user-mode component. - * component. This transaction will be - * completed when we get the value from - * the user-mode component. - * Set a timeout to deal with - * user-mode not responding. - */ - schedule_work(&kvp_sendkey_work); - schedule_delayed_work(&kvp_work, 5*HZ); - - return; - - } - -callback_done: - - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION - | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, recv_buffer, - recvlen, requestid, - VM_PKT_DATA_INBAND, 0); - } - -} - -int -hv_kvp_init(struct hv_util_service *srv) -{ - int err; - - err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback); - if (err) - return err; - recv_buffer = srv->recv_buffer; - - return 0; -} - -void hv_kvp_deinit(void) -{ - cn_del_callback(&kvp_id); - cancel_delayed_work_sync(&kvp_work); - cancel_work_sync(&kvp_sendkey_work); -} diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h deleted file mode 100644 index 9b765d7..0000000 --- a/drivers/staging/hv/hv_kvp.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * An implementation of HyperV key value pair (KVP) functionality for Linux. - * - * - * Copyright (C) 2010, Novell, Inc. - * Author : K. Y. Srinivasan - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _KVP_H -#define _KVP_H_ - -/* - * Maximum value size - used for both key names and value data, and includes - * any applicable NULL terminators. - * - * Note: This limit is somewhat arbitrary, but falls easily within what is - * supported for all native guests (back to Win 2000) and what is reasonable - * for the IC KVP exchange functionality. Note that Windows Me/98/95 are - * limited to 255 character key names. - * - * MSDN recommends not storing data values larger than 2048 bytes in the - * registry. - * - * Note: This value is used in defining the KVP exchange message - this value - * cannot be modified without affecting the message size and compatibility. - */ - -/* - * bytes, including any null terminators - */ -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) - - -/* - * Maximum key size - the registry limit for the length of an entry name - * is 256 characters, including the null terminator - */ - -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) - -/* - * In Linux, we implement the KVP functionality in two components: - * 1) The kernel component which is packaged as part of the hv_utils driver - * is responsible for communicating with the host and responsible for - * implementing the host/guest protocol. 2) A user level daemon that is - * responsible for data gathering. - * - * Host/Guest Protocol: The host iterates over an index and expects the guest - * to assign a key name to the index and also return the value corresponding to - * the key. The host will have atmost one KVP transaction outstanding at any - * given point in time. The host side iteration stops when the guest returns - * an error. Microsoft has specified the following mapping of key names to - * host specified index: - * - * Index Key Name - * 0 FullyQualifiedDomainName - * 1 IntegrationServicesVersion - * 2 NetworkAddressIPv4 - * 3 NetworkAddressIPv6 - * 4 OSBuildNumber - * 5 OSName - * 6 OSMajorVersion - * 7 OSMinorVersion - * 8 OSVersion - * 9 ProcessorArchitecture - * - * The Windows host expects the Key Name and Key Value to be encoded in utf16. - * - * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the - * data gathering functionality in a user mode daemon. The user level daemon - * is also responsible for binding the key name to the index as well. The - * kernel and user-level daemon communicate using a connector channel. - * - * The user mode component first registers with the - * the kernel component. Subsequently, the kernel component requests, data - * for the specified keys. In response to this message the user mode component - * fills in the value corresponding to the specified key. We overload the - * sequence field in the cn_msg header to define our KVP message types. - * - * - * The kernel component simply acts as a conduit for communication between the - * Windows host and the user-level daemon. The kernel component passes up the - * index received from the Host to the user-level daemon. If the index is - * valid (supported), the corresponding key as well as its - * value (both are strings) is returned. If the index is invalid - * (not supported), a NULL key string is returned. - */ - -/* - * - * The following definitions are shared with the user-mode component; do not - * change any of this without making the corresponding changes in - * the KVP user-mode component. - */ - -#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ -#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ - -enum hv_ku_op { - KVP_REGISTER = 0, /* Register the user mode component */ - KVP_KERNEL_GET, /* Kernel is requesting the value */ - KVP_KERNEL_SET, /* Kernel is providing the value */ - KVP_USER_GET, /* User is requesting the value */ - KVP_USER_SET /* User is providing the value */ -}; - -struct hv_ku_msg { - __u32 kvp_index; /* Key index */ - __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ - __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ -}; - - - - -#ifdef __KERNEL__ - -/* - * Registry value types. - */ - -#define REG_SZ 1 - -enum hv_kvp_exchg_op { - KVP_OP_GET = 0, - KVP_OP_SET, - KVP_OP_DELETE, - KVP_OP_ENUMERATE, - KVP_OP_COUNT /* Number of operations, must be last. */ -}; - -enum hv_kvp_exchg_pool { - KVP_POOL_EXTERNAL = 0, - KVP_POOL_GUEST, - KVP_POOL_AUTO, - KVP_POOL_AUTO_EXTERNAL, - KVP_POOL_AUTO_INTERNAL, - KVP_POOL_COUNT /* Number of pools, must be last. */ -}; - -struct hv_kvp_hdr { - u8 operation; - u8 pool; -}; - -struct hv_kvp_exchg_msg_value { - u32 value_type; - u32 key_size; - u32 value_size; - u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; - u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; -}; - -struct hv_kvp_msg_enumerate { - u32 index; - struct hv_kvp_exchg_msg_value data; -}; - -struct hv_kvp_msg { - struct hv_kvp_hdr kvp_hdr; - struct hv_kvp_msg_enumerate kvp_data; -}; - -int hv_kvp_init(struct hv_util_service *); -void hv_kvp_deinit(void); -void hv_kvp_onchannelcallback(void *); - -#endif /* __KERNEL__ */ -#endif /* _KVP_H */ - diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index edbb479..c354ade 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -22,8 +22,7 @@ #include #include #include - -#include "hyperv.h" +#include struct hv_input_dev_info { diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c deleted file mode 100644 index faa6607..0000000 --- a/drivers/staging/hv/hv_util.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2010, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hv_kvp.h" - - -static void shutdown_onchannelcallback(void *context); -static struct hv_util_service util_shutdown = { - .util_cb = shutdown_onchannelcallback, -}; - -static void timesync_onchannelcallback(void *context); -static struct hv_util_service util_timesynch = { - .util_cb = timesync_onchannelcallback, -}; - -static void heartbeat_onchannelcallback(void *context); -static struct hv_util_service util_heartbeat = { - .util_cb = heartbeat_onchannelcallback, -}; - -static struct hv_util_service util_kvp = { - .util_cb = hv_kvp_onchannelcallback, - .util_init = hv_kvp_init, - .util_deinit = hv_kvp_deinit, -}; - -static void shutdown_onchannelcallback(void *context) -{ - struct vmbus_channel *channel = context; - u32 recvlen; - u64 requestid; - u8 execute_shutdown = false; - u8 *shut_txf_buf = util_shutdown.recv_buffer; - - struct shutdown_msg_data *shutdown_msg; - - struct icmsg_hdr *icmsghdrp; - struct icmsg_negotiate *negop = NULL; - - vmbus_recvpacket(channel, shut_txf_buf, - PAGE_SIZE, &recvlen, &requestid); - - if (recvlen > 0) { - icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[ - sizeof(struct vmbuspipe_hdr)]; - - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); - } else { - shutdown_msg = - (struct shutdown_msg_data *)&shut_txf_buf[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - switch (shutdown_msg->flags) { - case 0: - case 1: - icmsghdrp->status = HV_S_OK; - execute_shutdown = true; - - pr_info("Shutdown request received -" - " graceful shutdown initiated\n"); - break; - default: - icmsghdrp->status = HV_E_FAIL; - execute_shutdown = false; - - pr_info("Shutdown request received -" - " Invalid request\n"); - break; - } - } - - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION - | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, shut_txf_buf, - recvlen, requestid, - VM_PKT_DATA_INBAND, 0); - } - - if (execute_shutdown == true) - orderly_poweroff(true); -} - -/* - * Set guest time to host UTC time. - */ -static inline void do_adj_guesttime(u64 hosttime) -{ - s64 host_tns; - struct timespec host_ts; - - host_tns = (hosttime - WLTIMEDELTA) * 100; - host_ts = ns_to_timespec(host_tns); - - do_settimeofday(&host_ts); -} - -/* - * Set the host time in a process context. - */ - -struct adj_time_work { - struct work_struct work; - u64 host_time; -}; - -static void hv_set_host_time(struct work_struct *work) -{ - struct adj_time_work *wrk; - - wrk = container_of(work, struct adj_time_work, work); - do_adj_guesttime(wrk->host_time); - kfree(wrk); -} - -/* - * Synchronize time with host after reboot, restore, etc. - * - * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM. - * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time - * message after the timesync channel is opened. Since the hv_utils module is - * loaded after hv_vmbus, the first message is usually missed. The other - * thing is, systime is automatically set to emulated hardware clock which may - * not be UTC time or in the same time zone. So, to override these effects, we - * use the first 50 time samples for initial system time setting. - */ -static inline void adj_guesttime(u64 hosttime, u8 flags) -{ - struct adj_time_work *wrk; - static s32 scnt = 50; - - wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC); - if (wrk == NULL) - return; - - wrk->host_time = hosttime; - if ((flags & ICTIMESYNCFLAG_SYNC) != 0) { - INIT_WORK(&wrk->work, hv_set_host_time); - schedule_work(&wrk->work); - return; - } - - if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) { - scnt--; - INIT_WORK(&wrk->work, hv_set_host_time); - schedule_work(&wrk->work); - } else - kfree(wrk); -} - -/* - * Time Sync Channel message handler. - */ -static void timesync_onchannelcallback(void *context) -{ - struct vmbus_channel *channel = context; - u32 recvlen; - u64 requestid; - struct icmsg_hdr *icmsghdrp; - struct ictimesync_data *timedatap; - u8 *time_txf_buf = util_timesynch.recv_buffer; - - vmbus_recvpacket(channel, time_txf_buf, - PAGE_SIZE, &recvlen, &requestid); - - if (recvlen > 0) { - icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[ - sizeof(struct vmbuspipe_hdr)]; - - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); - } else { - timedatap = (struct ictimesync_data *)&time_txf_buf[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - adj_guesttime(timedatap->parenttime, timedatap->flags); - } - - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION - | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, time_txf_buf, - recvlen, requestid, - VM_PKT_DATA_INBAND, 0); - } -} - -/* - * Heartbeat functionality. - * Every two seconds, Hyper-V send us a heartbeat request message. - * we respond to this message, and Hyper-V knows we are alive. - */ -static void heartbeat_onchannelcallback(void *context) -{ - struct vmbus_channel *channel = context; - u32 recvlen; - u64 requestid; - struct icmsg_hdr *icmsghdrp; - struct heartbeat_msg_data *heartbeat_msg; - u8 *hbeat_txf_buf = util_heartbeat.recv_buffer; - - vmbus_recvpacket(channel, hbeat_txf_buf, - PAGE_SIZE, &recvlen, &requestid); - - if (recvlen > 0) { - icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[ - sizeof(struct vmbuspipe_hdr)]; - - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); - } else { - heartbeat_msg = - (struct heartbeat_msg_data *)&hbeat_txf_buf[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - heartbeat_msg->seq_num += 1; - } - - icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION - | ICMSGHDRFLAG_RESPONSE; - - vmbus_sendpacket(channel, hbeat_txf_buf, - recvlen, requestid, - VM_PKT_DATA_INBAND, 0); - } -} - -static int util_probe(struct hv_device *dev, - const struct hv_vmbus_device_id *dev_id) -{ - struct hv_util_service *srv = - (struct hv_util_service *)dev_id->driver_data; - int ret; - - srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!srv->recv_buffer) - return -ENOMEM; - if (srv->util_init) { - ret = srv->util_init(srv); - if (ret) { - ret = -ENODEV; - goto error1; - } - } - - ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, - srv->util_cb, dev->channel); - if (ret) - goto error; - - hv_set_drvdata(dev, srv); - return 0; - -error: - if (srv->util_deinit) - srv->util_deinit(); -error1: - kfree(srv->recv_buffer); - return ret; -} - -static int util_remove(struct hv_device *dev) -{ - struct hv_util_service *srv = hv_get_drvdata(dev); - - vmbus_close(dev->channel); - if (srv->util_deinit) - srv->util_deinit(); - kfree(srv->recv_buffer); - - return 0; -} - -static const struct hv_vmbus_device_id id_table[] = { - /* Shutdown guid */ - { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) - .driver_data = (unsigned long)&util_shutdown }, - /* Time synch guid */ - { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) - .driver_data = (unsigned long)&util_timesynch }, - /* Heartbeat guid */ - { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) - .driver_data = (unsigned long)&util_heartbeat }, - /* KVP guid */ - { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) - .driver_data = (unsigned long)&util_kvp }, - { }, -}; - -MODULE_DEVICE_TABLE(vmbus, id_table); - -/* The one and only one */ -static struct hv_driver util_drv = { - .name = "hv_util", - .id_table = id_table, - .probe = util_probe, - .remove = util_remove, -}; - -static int __init init_hyperv_utils(void) -{ - pr_info("Registering HyperV Utility Driver\n"); - - return vmbus_driver_register(&util_drv); -} - -static void exit_hyperv_utils(void) -{ - pr_info("De-Registered HyperV Utility Driver\n"); - - vmbus_driver_unregister(&util_drv); -} - -module_init(init_hyperv_utils); -module_exit(exit_hyperv_utils); - -MODULE_DESCRIPTION("Hyper-V Utilities"); -MODULE_VERSION(HV_DRV_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h deleted file mode 100644 index edaa9e2..0000000 --- a/drivers/staging/hv/hyperv.h +++ /dev/null @@ -1,969 +0,0 @@ -/* - * - * Copyright (c) 2011, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ - -#ifndef _HYPERV_H -#define _HYPERV_H - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include - - -#define MAX_PAGE_BUFFER_COUNT 16 -#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */ - -#pragma pack(push, 1) - -/* Single-page buffer */ -struct hv_page_buffer { - u32 len; - u32 offset; - u64 pfn; -}; - -/* Multiple-page buffer */ -struct hv_multipage_buffer { - /* Length and Offset determines the # of pfns in the array */ - u32 len; - u32 offset; - u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT]; -}; - -/* 0x18 includes the proprietary packet header */ -#define MAX_PAGE_BUFFER_PACKET (0x18 + \ - (sizeof(struct hv_page_buffer) * \ - MAX_PAGE_BUFFER_COUNT)) -#define MAX_MULTIPAGE_BUFFER_PACKET (0x18 + \ - sizeof(struct hv_multipage_buffer)) - - -#pragma pack(pop) - -struct hv_ring_buffer { - /* Offset in bytes from the start of ring data below */ - u32 write_index; - - /* Offset in bytes from the start of ring data below */ - u32 read_index; - - u32 interrupt_mask; - - /* Pad it to PAGE_SIZE so that data starts on page boundary */ - u8 reserved[4084]; - - /* NOTE: - * The interrupt_mask field is used only for channels but since our - * vmbus connection also uses this data structure and its data starts - * here, we commented out this field. - */ - - /* - * Ring data starts here + RingDataStartOffset - * !!! DO NOT place any fields below this !!! - */ - u8 buffer[0]; -} __packed; - -struct hv_ring_buffer_info { - struct hv_ring_buffer *ring_buffer; - u32 ring_size; /* Include the shared header */ - spinlock_t ring_lock; - - u32 ring_datasize; /* < ring_size */ - u32 ring_data_startoffset; -}; - -struct hv_ring_buffer_debug_info { - u32 current_interrupt_mask; - u32 current_read_index; - u32 current_write_index; - u32 bytes_avail_toread; - u32 bytes_avail_towrite; -}; - -/* - * We use the same version numbering for all Hyper-V modules. - * - * Definition of versioning is as follows; - * - * Major Number Changes for these scenarios; - * 1. When a new version of Windows Hyper-V - * is released. - * 2. A Major change has occurred in the - * Linux IC's. - * (For example the merge for the first time - * into the kernel) Every time the Major Number - * changes, the Revision number is reset to 0. - * Minor Number Changes when new functionality is added - * to the Linux IC's that is not a bug fix. - * - * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync - */ -#define HV_DRV_VERSION "3.1" - - -/* - * A revision number of vmbus that is used for ensuring both ends on a - * partition are using compatible versions. - */ -#define VMBUS_REVISION_NUMBER 13 - -/* Make maximum size of pipe payload of 16K */ -#define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384) - -/* Define PipeMode values. */ -#define VMBUS_PIPE_TYPE_BYTE 0x00000000 -#define VMBUS_PIPE_TYPE_MESSAGE 0x00000004 - -/* The size of the user defined data buffer for non-pipe offers. */ -#define MAX_USER_DEFINED_BYTES 120 - -/* The size of the user defined data buffer for pipe offers. */ -#define MAX_PIPE_USER_DEFINED_BYTES 116 - -/* - * At the center of the Channel Management library is the Channel Offer. This - * struct contains the fundamental information about an offer. - */ -struct vmbus_channel_offer { - uuid_le if_type; - uuid_le if_instance; - u64 int_latency; /* in 100ns units */ - u32 if_revision; - u32 server_ctx_size; /* in bytes */ - u16 chn_flags; - u16 mmio_megabytes; /* in bytes * 1024 * 1024 */ - - union { - /* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */ - struct { - unsigned char user_def[MAX_USER_DEFINED_BYTES]; - } std; - - /* - * Pipes: - * The following sructure is an integrated pipe protocol, which - * is implemented on top of standard user-defined data. Pipe - * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own - * use. - */ - struct { - u32 pipe_mode; - unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES]; - } pipe; - } u; - u32 padding; -} __packed; - -/* Server Flags */ -#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 1 -#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 2 -#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 4 -#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 -#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 -#define VMBUS_CHANNEL_PARENT_OFFER 0x200 -#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 - -struct vmpacket_descriptor { - u16 type; - u16 offset8; - u16 len8; - u16 flags; - u64 trans_id; -} __packed; - -struct vmpacket_header { - u32 prev_pkt_start_offset; - struct vmpacket_descriptor descriptor; -} __packed; - -struct vmtransfer_page_range { - u32 byte_count; - u32 byte_offset; -} __packed; - -struct vmtransfer_page_packet_header { - struct vmpacket_descriptor d; - u16 xfer_pageset_id; - bool sender_owns_set; - u8 reserved; - u32 range_cnt; - struct vmtransfer_page_range ranges[1]; -} __packed; - -struct vmgpadl_packet_header { - struct vmpacket_descriptor d; - u32 gpadl; - u32 reserved; -} __packed; - -struct vmadd_remove_transfer_page_set { - struct vmpacket_descriptor d; - u32 gpadl; - u16 xfer_pageset_id; - u16 reserved; -} __packed; - -/* - * This structure defines a range in guest physical space that can be made to - * look virtually contiguous. - */ -struct gpa_range { - u32 byte_count; - u32 byte_offset; - u64 pfn_array[0]; -}; - -/* - * This is the format for an Establish Gpadl packet, which contains a handle by - * which this GPADL will be known and a set of GPA ranges associated with it. - * This can be converted to a MDL by the guest OS. If there are multiple GPA - * ranges, then the resulting MDL will be "chained," representing multiple VA - * ranges. - */ -struct vmestablish_gpadl { - struct vmpacket_descriptor d; - u32 gpadl; - u32 range_cnt; - struct gpa_range range[1]; -} __packed; - -/* - * This is the format for a Teardown Gpadl packet, which indicates that the - * GPADL handle in the Establish Gpadl packet will never be referenced again. - */ -struct vmteardown_gpadl { - struct vmpacket_descriptor d; - u32 gpadl; - u32 reserved; /* for alignment to a 8-byte boundary */ -} __packed; - -/* - * This is the format for a GPA-Direct packet, which contains a set of GPA - * ranges, in addition to commands and/or data. - */ -struct vmdata_gpa_direct { - struct vmpacket_descriptor d; - u32 reserved; - u32 range_cnt; - struct gpa_range range[1]; -} __packed; - -/* This is the format for a Additional Data Packet. */ -struct vmadditional_data { - struct vmpacket_descriptor d; - u64 total_bytes; - u32 offset; - u32 byte_cnt; - unsigned char data[1]; -} __packed; - -union vmpacket_largest_possible_header { - struct vmpacket_descriptor simple_hdr; - struct vmtransfer_page_packet_header xfer_page_hdr; - struct vmgpadl_packet_header gpadl_hdr; - struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr; - struct vmestablish_gpadl establish_gpadl_hdr; - struct vmteardown_gpadl teardown_gpadl_hdr; - struct vmdata_gpa_direct data_gpa_direct_hdr; -}; - -#define VMPACKET_DATA_START_ADDRESS(__packet) \ - (void *)(((unsigned char *)__packet) + \ - ((struct vmpacket_descriptor)__packet)->offset8 * 8) - -#define VMPACKET_DATA_LENGTH(__packet) \ - ((((struct vmpacket_descriptor)__packet)->len8 - \ - ((struct vmpacket_descriptor)__packet)->offset8) * 8) - -#define VMPACKET_TRANSFER_MODE(__packet) \ - (((struct IMPACT)__packet)->type) - -enum vmbus_packet_type { - VM_PKT_INVALID = 0x0, - VM_PKT_SYNCH = 0x1, - VM_PKT_ADD_XFER_PAGESET = 0x2, - VM_PKT_RM_XFER_PAGESET = 0x3, - VM_PKT_ESTABLISH_GPADL = 0x4, - VM_PKT_TEARDOWN_GPADL = 0x5, - VM_PKT_DATA_INBAND = 0x6, - VM_PKT_DATA_USING_XFER_PAGES = 0x7, - VM_PKT_DATA_USING_GPADL = 0x8, - VM_PKT_DATA_USING_GPA_DIRECT = 0x9, - VM_PKT_CANCEL_REQUEST = 0xa, - VM_PKT_COMP = 0xb, - VM_PKT_DATA_USING_ADDITIONAL_PKT = 0xc, - VM_PKT_ADDITIONAL_DATA = 0xd -}; - -#define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED 1 - - -/* Version 1 messages */ -enum vmbus_channel_message_type { - CHANNELMSG_INVALID = 0, - CHANNELMSG_OFFERCHANNEL = 1, - CHANNELMSG_RESCIND_CHANNELOFFER = 2, - CHANNELMSG_REQUESTOFFERS = 3, - CHANNELMSG_ALLOFFERS_DELIVERED = 4, - CHANNELMSG_OPENCHANNEL = 5, - CHANNELMSG_OPENCHANNEL_RESULT = 6, - CHANNELMSG_CLOSECHANNEL = 7, - CHANNELMSG_GPADL_HEADER = 8, - CHANNELMSG_GPADL_BODY = 9, - CHANNELMSG_GPADL_CREATED = 10, - CHANNELMSG_GPADL_TEARDOWN = 11, - CHANNELMSG_GPADL_TORNDOWN = 12, - CHANNELMSG_RELID_RELEASED = 13, - CHANNELMSG_INITIATE_CONTACT = 14, - CHANNELMSG_VERSION_RESPONSE = 15, - CHANNELMSG_UNLOAD = 16, -#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD - CHANNELMSG_VIEWRANGE_ADD = 17, - CHANNELMSG_VIEWRANGE_REMOVE = 18, -#endif - CHANNELMSG_COUNT -}; - -struct vmbus_channel_message_header { - enum vmbus_channel_message_type msgtype; - u32 padding; -} __packed; - -/* Query VMBus Version parameters */ -struct vmbus_channel_query_vmbus_version { - struct vmbus_channel_message_header header; - u32 version; -} __packed; - -/* VMBus Version Supported parameters */ -struct vmbus_channel_version_supported { - struct vmbus_channel_message_header header; - bool version_supported; -} __packed; - -/* Offer Channel parameters */ -struct vmbus_channel_offer_channel { - struct vmbus_channel_message_header header; - struct vmbus_channel_offer offer; - u32 child_relid; - u8 monitorid; - bool monitor_allocated; -} __packed; - -/* Rescind Offer parameters */ -struct vmbus_channel_rescind_offer { - struct vmbus_channel_message_header header; - u32 child_relid; -} __packed; - -/* - * Request Offer -- no parameters, SynIC message contains the partition ID - * Set Snoop -- no parameters, SynIC message contains the partition ID - * Clear Snoop -- no parameters, SynIC message contains the partition ID - * All Offers Delivered -- no parameters, SynIC message contains the partition - * ID - * Flush Client -- no parameters, SynIC message contains the partition ID - */ - -/* Open Channel parameters */ -struct vmbus_channel_open_channel { - struct vmbus_channel_message_header header; - - /* Identifies the specific VMBus channel that is being opened. */ - u32 child_relid; - - /* ID making a particular open request at a channel offer unique. */ - u32 openid; - - /* GPADL for the channel's ring buffer. */ - u32 ringbuffer_gpadlhandle; - - /* GPADL for the channel's server context save area. */ - u32 server_contextarea_gpadlhandle; - - /* - * The upstream ring buffer begins at offset zero in the memory - * described by RingBufferGpadlHandle. The downstream ring buffer - * follows it at this offset (in pages). - */ - u32 downstream_ringbuffer_pageoffset; - - /* User-specific data to be passed along to the server endpoint. */ - unsigned char userdata[MAX_USER_DEFINED_BYTES]; -} __packed; - -/* Open Channel Result parameters */ -struct vmbus_channel_open_result { - struct vmbus_channel_message_header header; - u32 child_relid; - u32 openid; - u32 status; -} __packed; - -/* Close channel parameters; */ -struct vmbus_channel_close_channel { - struct vmbus_channel_message_header header; - u32 child_relid; -} __packed; - -/* Channel Message GPADL */ -#define GPADL_TYPE_RING_BUFFER 1 -#define GPADL_TYPE_SERVER_SAVE_AREA 2 -#define GPADL_TYPE_TRANSACTION 8 - -/* - * The number of PFNs in a GPADL message is defined by the number of - * pages that would be spanned by ByteCount and ByteOffset. If the - * implied number of PFNs won't fit in this packet, there will be a - * follow-up packet that contains more. - */ -struct vmbus_channel_gpadl_header { - struct vmbus_channel_message_header header; - u32 child_relid; - u32 gpadl; - u16 range_buflen; - u16 rangecount; - struct gpa_range range[0]; -} __packed; - -/* This is the followup packet that contains more PFNs. */ -struct vmbus_channel_gpadl_body { - struct vmbus_channel_message_header header; - u32 msgnumber; - u32 gpadl; - u64 pfn[0]; -} __packed; - -struct vmbus_channel_gpadl_created { - struct vmbus_channel_message_header header; - u32 child_relid; - u32 gpadl; - u32 creation_status; -} __packed; - -struct vmbus_channel_gpadl_teardown { - struct vmbus_channel_message_header header; - u32 child_relid; - u32 gpadl; -} __packed; - -struct vmbus_channel_gpadl_torndown { - struct vmbus_channel_message_header header; - u32 gpadl; -} __packed; - -#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD -struct vmbus_channel_view_range_add { - struct vmbus_channel_message_header header; - PHYSICAL_ADDRESS viewrange_base; - u64 viewrange_length; - u32 child_relid; -} __packed; - -struct vmbus_channel_view_range_remove { - struct vmbus_channel_message_header header; - PHYSICAL_ADDRESS viewrange_base; - u32 child_relid; -} __packed; -#endif - -struct vmbus_channel_relid_released { - struct vmbus_channel_message_header header; - u32 child_relid; -} __packed; - -struct vmbus_channel_initiate_contact { - struct vmbus_channel_message_header header; - u32 vmbus_version_requested; - u32 padding2; - u64 interrupt_page; - u64 monitor_page1; - u64 monitor_page2; -} __packed; - -struct vmbus_channel_version_response { - struct vmbus_channel_message_header header; - bool version_supported; -} __packed; - -enum vmbus_channel_state { - CHANNEL_OFFER_STATE, - CHANNEL_OPENING_STATE, - CHANNEL_OPEN_STATE, -}; - -struct vmbus_channel_debug_info { - u32 relid; - enum vmbus_channel_state state; - uuid_le interfacetype; - uuid_le interface_instance; - u32 monitorid; - u32 servermonitor_pending; - u32 servermonitor_latency; - u32 servermonitor_connectionid; - u32 clientmonitor_pending; - u32 clientmonitor_latency; - u32 clientmonitor_connectionid; - - struct hv_ring_buffer_debug_info inbound; - struct hv_ring_buffer_debug_info outbound; -}; - -/* - * Represents each channel msg on the vmbus connection This is a - * variable-size data structure depending on the msg type itself - */ -struct vmbus_channel_msginfo { - /* Bookkeeping stuff */ - struct list_head msglistentry; - - /* So far, this is only used to handle gpadl body message */ - struct list_head submsglist; - - /* Synchronize the request/response if needed */ - struct completion waitevent; - union { - struct vmbus_channel_version_supported version_supported; - struct vmbus_channel_open_result open_result; - struct vmbus_channel_gpadl_torndown gpadl_torndown; - struct vmbus_channel_gpadl_created gpadl_created; - struct vmbus_channel_version_response version_response; - } response; - - u32 msgsize; - /* - * The channel message that goes out on the "wire". - * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header - */ - unsigned char msg[0]; -}; - -struct vmbus_close_msg { - struct vmbus_channel_msginfo info; - struct vmbus_channel_close_channel msg; -}; - -struct vmbus_channel { - struct list_head listentry; - - struct hv_device *device_obj; - - struct work_struct work; - - enum vmbus_channel_state state; - - struct vmbus_channel_offer_channel offermsg; - /* - * These are based on the OfferMsg.MonitorId. - * Save it here for easy access. - */ - u8 monitor_grp; - u8 monitor_bit; - - u32 ringbuffer_gpadlhandle; - - /* Allocated memory for ring buffer */ - void *ringbuffer_pages; - u32 ringbuffer_pagecount; - struct hv_ring_buffer_info outbound; /* send to parent */ - struct hv_ring_buffer_info inbound; /* receive from parent */ - spinlock_t inbound_lock; - struct workqueue_struct *controlwq; - - struct vmbus_close_msg close_msg; - - /* Channel callback are invoked in this workqueue context */ - /* HANDLE dataWorkQueue; */ - - void (*onchannel_callback)(void *context); - void *channel_callback_context; -}; - -void free_channel(struct vmbus_channel *channel); - -void vmbus_onmessage(void *context); - -int vmbus_request_offers(void); - -/* The format must be the same as struct vmdata_gpa_direct */ -struct vmbus_channel_packet_page_buffer { - u16 type; - u16 dataoffset8; - u16 length8; - u16 flags; - u64 transactionid; - u32 reserved; - u32 rangecount; - struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT]; -} __packed; - -/* The format must be the same as struct vmdata_gpa_direct */ -struct vmbus_channel_packet_multipage_buffer { - u16 type; - u16 dataoffset8; - u16 length8; - u16 flags; - u64 transactionid; - u32 reserved; - u32 rangecount; /* Always 1 in this case */ - struct hv_multipage_buffer range; -} __packed; - - -extern int vmbus_open(struct vmbus_channel *channel, - u32 send_ringbuffersize, - u32 recv_ringbuffersize, - void *userdata, - u32 userdatalen, - void(*onchannel_callback)(void *context), - void *context); - -extern void vmbus_close(struct vmbus_channel *channel); - -extern int vmbus_sendpacket(struct vmbus_channel *channel, - const void *buffer, - u32 bufferLen, - u64 requestid, - enum vmbus_packet_type type, - u32 flags); - -extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, - struct hv_page_buffer pagebuffers[], - u32 pagecount, - void *buffer, - u32 bufferlen, - u64 requestid); - -extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, - struct hv_multipage_buffer *mpb, - void *buffer, - u32 bufferlen, - u64 requestid); - -extern int vmbus_establish_gpadl(struct vmbus_channel *channel, - void *kbuffer, - u32 size, - u32 *gpadl_handle); - -extern int vmbus_teardown_gpadl(struct vmbus_channel *channel, - u32 gpadl_handle); - -extern int vmbus_recvpacket(struct vmbus_channel *channel, - void *buffer, - u32 bufferlen, - u32 *buffer_actual_len, - u64 *requestid); - -extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, - void *buffer, - u32 bufferlen, - u32 *buffer_actual_len, - u64 *requestid); - - -extern void vmbus_get_debug_info(struct vmbus_channel *channel, - struct vmbus_channel_debug_info *debug); - -extern void vmbus_ontimer(unsigned long data); - - -#define LOWORD(dw) ((unsigned short)(dw)) -#define HIWORD(dw) ((unsigned short)(((unsigned int) (dw) >> 16) & 0xFFFF)) - - -#define VMBUS 0x0001 -#define STORVSC 0x0002 -#define NETVSC 0x0004 -#define INPUTVSC 0x0008 -#define BLKVSC 0x0010 -#define VMBUS_DRV 0x0100 -#define STORVSC_DRV 0x0200 -#define NETVSC_DRV 0x0400 -#define INPUTVSC_DRV 0x0800 -#define BLKVSC_DRV 0x1000 - -#define ALL_MODULES (VMBUS |\ - STORVSC |\ - NETVSC |\ - INPUTVSC |\ - BLKVSC |\ - VMBUS_DRV |\ - STORVSC_DRV |\ - NETVSC_DRV |\ - INPUTVSC_DRV|\ - BLKVSC_DRV) - -/* Logging Level */ -#define ERROR_LVL 3 -#define WARNING_LVL 4 -#define INFO_LVL 6 -#define DEBUG_LVL 7 -#define DEBUG_LVL_ENTEREXIT 8 -#define DEBUG_RING_LVL 9 - -extern unsigned int vmbus_loglevel; - -#define DPRINT(mod, lvl, fmt, args...) do {\ - if ((mod & (HIWORD(vmbus_loglevel))) && \ - (lvl <= LOWORD(vmbus_loglevel))) \ - printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\ - } while (0) - -#define DPRINT_DBG(mod, fmt, args...) do {\ - if ((mod & (HIWORD(vmbus_loglevel))) && \ - (DEBUG_LVL <= LOWORD(vmbus_loglevel))) \ - printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\ - } while (0) - -#define DPRINT_INFO(mod, fmt, args...) do {\ - if ((mod & (HIWORD(vmbus_loglevel))) && \ - (INFO_LVL <= LOWORD(vmbus_loglevel))) \ - printk(KERN_INFO #mod": " fmt "\n", ## args);\ - } while (0) - -#define DPRINT_WARN(mod, fmt, args...) do {\ - if ((mod & (HIWORD(vmbus_loglevel))) && \ - (WARNING_LVL <= LOWORD(vmbus_loglevel))) \ - printk(KERN_WARNING #mod": WARNING! " fmt "\n", ## args);\ - } while (0) - -#define DPRINT_ERR(mod, fmt, args...) do {\ - if ((mod & (HIWORD(vmbus_loglevel))) && \ - (ERROR_LVL <= LOWORD(vmbus_loglevel))) \ - printk(KERN_ERR #mod": %s() ERROR!! " fmt "\n", \ - __func__, ## args);\ - } while (0) - - - -struct hv_driver; -struct hv_device; - -struct hv_dev_port_info { - u32 int_mask; - u32 read_idx; - u32 write_idx; - u32 bytes_avail_toread; - u32 bytes_avail_towrite; -}; - -struct hv_device_info { - u32 chn_id; - u32 chn_state; - uuid_le chn_type; - uuid_le chn_instance; - - u32 monitor_id; - u32 server_monitor_pending; - u32 server_monitor_latency; - u32 server_monitor_conn_id; - u32 client_monitor_pending; - u32 client_monitor_latency; - u32 client_monitor_conn_id; - - struct hv_dev_port_info inbound; - struct hv_dev_port_info outbound; -}; - -/* Base driver object */ -struct hv_driver { - const char *name; - - /* the device type supported by this driver */ - uuid_le dev_type; - const struct hv_vmbus_device_id *id_table; - - struct device_driver driver; - - int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *); - int (*remove)(struct hv_device *); - void (*shutdown)(struct hv_device *); - -}; - -/* Base device object */ -struct hv_device { - /* the device type id of this device */ - uuid_le dev_type; - - /* the device instance id of this device */ - uuid_le dev_instance; - - struct device device; - - struct vmbus_channel *channel; -}; - - -static inline struct hv_device *device_to_hv_device(struct device *d) -{ - return container_of(d, struct hv_device, device); -} - -static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) -{ - return container_of(d, struct hv_driver, driver); -} - -static inline void hv_set_drvdata(struct hv_device *dev, void *data) -{ - dev_set_drvdata(&dev->device, data); -} - -static inline void *hv_get_drvdata(struct hv_device *dev) -{ - return dev_get_drvdata(&dev->device); -} - -/* Vmbus interface */ -#define vmbus_driver_register(driver) \ - __vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) -int __must_check __vmbus_driver_register(struct hv_driver *hv_driver, - struct module *owner, - const char *mod_name); -void vmbus_driver_unregister(struct hv_driver *hv_driver); - -/** - * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device - * - * This macro is used to create a struct hv_vmbus_device_id that matches a - * specific device. - */ -#define VMBUS_DEVICE(g0, g1, g2, g3, g4, g5, g6, g7, \ - g8, g9, ga, gb, gc, gd, ge, gf) \ - .guid = { g0, g1, g2, g3, g4, g5, g6, g7, \ - g8, g9, ga, gb, gc, gd, ge, gf }, - -/* - * Common header for Hyper-V ICs - */ - -#define ICMSGTYPE_NEGOTIATE 0 -#define ICMSGTYPE_HEARTBEAT 1 -#define ICMSGTYPE_KVPEXCHANGE 2 -#define ICMSGTYPE_SHUTDOWN 3 -#define ICMSGTYPE_TIMESYNC 4 -#define ICMSGTYPE_VSS 5 - -#define ICMSGHDRFLAG_TRANSACTION 1 -#define ICMSGHDRFLAG_REQUEST 2 -#define ICMSGHDRFLAG_RESPONSE 4 - -#define HV_S_OK 0x00000000 -#define HV_E_FAIL 0x80004005 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 - -/* - * While we want to handle util services as regular devices, - * there is only one instance of each of these services; so - * we statically allocate the service specific state. - */ - -struct hv_util_service { - u8 *recv_buffer; - void (*util_cb)(void *); - int (*util_init)(struct hv_util_service *); - void (*util_deinit)(void); -}; - -struct vmbuspipe_hdr { - u32 flags; - u32 msgsize; -} __packed; - -struct ic_version { - u16 major; - u16 minor; -} __packed; - -struct icmsg_hdr { - struct ic_version icverframe; - u16 icmsgtype; - struct ic_version icvermsg; - u16 icmsgsize; - u32 status; - u8 ictransaction_id; - u8 icflags; - u8 reserved[2]; -} __packed; - -struct icmsg_negotiate { - u16 icframe_vercnt; - u16 icmsg_vercnt; - u32 reserved; - struct ic_version icversion_data[1]; /* any size array */ -} __packed; - -struct shutdown_msg_data { - u32 reason_code; - u32 timeout_seconds; - u32 flags; - u8 display_message[2048]; -} __packed; - -struct heartbeat_msg_data { - u64 seq_num; - u32 reserved[8]; -} __packed; - -/* Time Sync IC defs */ -#define ICTIMESYNCFLAG_PROBE 0 -#define ICTIMESYNCFLAG_SYNC 1 -#define ICTIMESYNCFLAG_SAMPLE 2 - -#ifdef __x86_64__ -#define WLTIMEDELTA 116444736000000000L /* in 100ns unit */ -#else -#define WLTIMEDELTA 116444736000000000LL -#endif - -struct ictimesync_data { - u64 parenttime; - u64 childtime; - u64 roundtriptime; - u8 flags; -} __packed; - -struct hyperv_service_callback { - u8 msg_type; - char *log_msg; - uuid_le data; - struct vmbus_channel *channel; - void (*callback) (void *context); -}; - -extern void prep_negotiate_resp(struct icmsg_hdr *, - struct icmsg_negotiate *, u8 *); - -#endif /* _HYPERV_H */ diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index 366dd2b..ac1ec84 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -26,7 +26,7 @@ #define _HYPERV_NET_H #include -#include "hyperv.h" +#include /* Fwd declaration */ struct hv_netvsc_packet; diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h deleted file mode 100644 index 3d2d836..0000000 --- a/drivers/staging/hv/hyperv_vmbus.h +++ /dev/null @@ -1,629 +0,0 @@ -/* - * - * Copyright (c) 2011, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ - -#ifndef _HYPERV_VMBUS_H -#define _HYPERV_VMBUS_H - -#include -#include -#include - -#include "hyperv.h" - -/* - * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent - * is set by CPUID(HVCPUID_VERSION_FEATURES). - */ -enum hv_cpuid_function { - HVCPUID_VERSION_FEATURES = 0x00000001, - HVCPUID_VENDOR_MAXFUNCTION = 0x40000000, - HVCPUID_INTERFACE = 0x40000001, - - /* - * The remaining functions depend on the value of - * HVCPUID_INTERFACE - */ - HVCPUID_VERSION = 0x40000002, - HVCPUID_FEATURES = 0x40000003, - HVCPUID_ENLIGHTENMENT_INFO = 0x40000004, - HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005, -}; - -/* Define version of the synthetic interrupt controller. */ -#define HV_SYNIC_VERSION (1) - -/* Define the expected SynIC version. */ -#define HV_SYNIC_VERSION_1 (0x1) - -/* Define synthetic interrupt controller message constants. */ -#define HV_MESSAGE_SIZE (256) -#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) -#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) -#define HV_ANY_VP (0xFFFFFFFF) - -/* Define synthetic interrupt controller flag constants. */ -#define HV_EVENT_FLAGS_COUNT (256 * 8) -#define HV_EVENT_FLAGS_BYTE_COUNT (256) -#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(u32)) - -/* Define hypervisor message types. */ -enum hv_message_type { - HVMSG_NONE = 0x00000000, - - /* Memory access messages. */ - HVMSG_UNMAPPED_GPA = 0x80000000, - HVMSG_GPA_INTERCEPT = 0x80000001, - - /* Timer notification messages. */ - HVMSG_TIMER_EXPIRED = 0x80000010, - - /* Error messages. */ - HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020, - HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021, - HVMSG_UNSUPPORTED_FEATURE = 0x80000022, - - /* Trace buffer complete messages. */ - HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040, - - /* Platform-specific processor intercept messages. */ - HVMSG_X64_IOPORT_INTERCEPT = 0x80010000, - HVMSG_X64_MSR_INTERCEPT = 0x80010001, - HVMSG_X64_CPUID_INTERCEPT = 0x80010002, - HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, - HVMSG_X64_APIC_EOI = 0x80010004, - HVMSG_X64_LEGACY_FP_ERROR = 0x80010005 -}; - -/* Define the number of synthetic interrupt sources. */ -#define HV_SYNIC_SINT_COUNT (16) -#define HV_SYNIC_STIMER_COUNT (4) - -/* Define invalid partition identifier. */ -#define HV_PARTITION_ID_INVALID ((u64)0x0) - -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - -/* Define port identifier type. */ -union hv_port_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u ; -}; - -/* Define port type. */ -enum hv_port_type { - HVPORT_MSG = 1, - HVPORT_EVENT = 2, - HVPORT_MONITOR = 3 -}; - -/* Define port information structure. */ -struct hv_port_info { - enum hv_port_type port_type; - u32 padding; - union { - struct { - u32 target_sint; - u32 target_vp; - u64 rsvdz; - } message_port_info; - struct { - u32 target_sint; - u32 target_vp; - u16 base_flag_bumber; - u16 flag_count; - u32 rsvdz; - } event_port_info; - struct { - u64 monitor_address; - u64 rsvdz; - } monitor_port_info; - }; -}; - -struct hv_connection_info { - enum hv_port_type port_type; - u32 padding; - union { - struct { - u64 rsvdz; - } message_connection_info; - struct { - u64 rsvdz; - } event_connection_info; - struct { - u64 monitor_address; - } monitor_connection_info; - }; -}; - -/* Define synthetic interrupt controller message flags. */ -union hv_message_flags { - u8 asu8; - struct { - u8 msg_pending:1; - u8 reserved:7; - }; -}; - -/* Define synthetic interrupt controller message header. */ -struct hv_message_header { - enum hv_message_type message_type; - u8 payload_size; - union hv_message_flags message_flags; - u8 reserved[2]; - union { - u64 sender; - union hv_port_id port; - }; -}; - -/* Define timer message payload structure. */ -struct hv_timer_message_payload { - u32 timer_index; - u32 reserved; - u64 expiration_time; /* When the timer expired */ - u64 delivery_time; /* When the message was delivered */ -}; - -/* Define synthetic interrupt controller message format. */ -struct hv_message { - struct hv_message_header header; - union { - u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; - } u ; -}; - -/* Define the number of message buffers associated with each port. */ -#define HV_PORT_MESSAGE_BUFFER_COUNT (16) - -/* Define the synthetic interrupt message page layout. */ -struct hv_message_page { - struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; -}; - -/* Define the synthetic interrupt controller event flags format. */ -union hv_synic_event_flags { - u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT]; - u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT]; -}; - -/* Define the synthetic interrupt flags page layout. */ -struct hv_synic_event_flags_page { - union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT]; -}; - -/* Define SynIC control register. */ -union hv_synic_scontrol { - u64 as_uint64; - struct { - u64 enable:1; - u64 reserved:63; - }; -}; - -/* Define synthetic interrupt source. */ -union hv_synic_sint { - u64 as_uint64; - struct { - u64 vector:8; - u64 reserved1:8; - u64 masked:1; - u64 auto_eoi:1; - u64 reserved2:46; - }; -}; - -/* Define the format of the SIMP register */ -union hv_synic_simp { - u64 as_uint64; - struct { - u64 simp_enabled:1; - u64 preserved:11; - u64 base_simp_gpa:52; - }; -}; - -/* Define the format of the SIEFP register */ -union hv_synic_siefp { - u64 as_uint64; - struct { - u64 siefp_enabled:1; - u64 preserved:11; - u64 base_siefp_gpa:52; - }; -}; - -/* Definitions for the monitored notification facility */ -union hv_monitor_trigger_group { - u64 as_uint64; - struct { - u32 pending; - u32 armed; - }; -}; - -struct hv_monitor_parameter { - union hv_connection_id connectionid; - u16 flagnumber; - u16 rsvdz; -}; - -union hv_monitor_trigger_state { - u32 asu32; - - struct { - u32 group_enable:4; - u32 rsvdz:28; - }; -}; - -/* struct hv_monitor_page Layout */ -/* ------------------------------------------------------ */ -/* | 0 | TriggerState (4 bytes) | Rsvd1 (4 bytes) | */ -/* | 8 | TriggerGroup[0] | */ -/* | 10 | TriggerGroup[1] | */ -/* | 18 | TriggerGroup[2] | */ -/* | 20 | TriggerGroup[3] | */ -/* | 28 | Rsvd2[0] | */ -/* | 30 | Rsvd2[1] | */ -/* | 38 | Rsvd2[2] | */ -/* | 40 | NextCheckTime[0][0] | NextCheckTime[0][1] | */ -/* | ... | */ -/* | 240 | Latency[0][0..3] | */ -/* | 340 | Rsvz3[0] | */ -/* | 440 | Parameter[0][0] | */ -/* | 448 | Parameter[0][1] | */ -/* | ... | */ -/* | 840 | Rsvd4[0] | */ -/* ------------------------------------------------------ */ -struct hv_monitor_page { - union hv_monitor_trigger_state trigger_state; - u32 rsvdz1; - - union hv_monitor_trigger_group trigger_group[4]; - u64 rsvdz2[3]; - - s32 next_checktime[4][32]; - - u16 latency[4][32]; - u64 rsvdz3[32]; - - struct hv_monitor_parameter parameter[4][32]; - - u8 rsvdz4[1984]; -}; - -/* Declare the various hypercall operations. */ -enum hv_call_code { - HVCALL_POST_MESSAGE = 0x005c, - HVCALL_SIGNAL_EVENT = 0x005d, -}; - -/* Definition of the hv_post_message hypercall input structure. */ -struct hv_input_post_message { - union hv_connection_id connectionid; - u32 reserved; - enum hv_message_type message_type; - u32 payload_size; - u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; -}; - -/* Definition of the hv_signal_event hypercall input structure. */ -struct hv_input_signal_event { - union hv_connection_id connectionid; - u16 flag_number; - u16 rsvdz; -}; - -/* - * Versioning definitions used for guests reporting themselves to the - * hypervisor, and visa versa. - */ - -/* Version info reported by guest OS's */ -enum hv_guest_os_vendor { - HVGUESTOS_VENDOR_MICROSOFT = 0x0001 -}; - -enum hv_guest_os_microsoft_ids { - HVGUESTOS_MICROSOFT_UNDEFINED = 0x00, - HVGUESTOS_MICROSOFT_MSDOS = 0x01, - HVGUESTOS_MICROSOFT_WINDOWS3X = 0x02, - HVGUESTOS_MICROSOFT_WINDOWS9X = 0x03, - HVGUESTOS_MICROSOFT_WINDOWSNT = 0x04, - HVGUESTOS_MICROSOFT_WINDOWSCE = 0x05 -}; - -/* - * Declare the MSR used to identify the guest OS. - */ -#define HV_X64_MSR_GUEST_OS_ID 0x40000000 - -union hv_x64_msr_guest_os_id_contents { - u64 as_uint64; - struct { - u64 build_number:16; - u64 service_version:8; /* Service Pack, etc. */ - u64 minor_version:8; - u64 major_version:8; - u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */ - u64 vendor_id:16; /* enum hv_guest_os_vendor */ - }; -}; - -/* - * Declare the MSR used to setup pages used to communicate with the hypervisor. - */ -#define HV_X64_MSR_HYPERCALL 0x40000001 - -union hv_x64_msr_hypercall_contents { - u64 as_uint64; - struct { - u64 enable:1; - u64 reserved:11; - u64 guest_physical_address:52; - }; -}; - - -enum { - VMBUS_MESSAGE_CONNECTION_ID = 1, - VMBUS_MESSAGE_PORT_ID = 1, - VMBUS_EVENT_CONNECTION_ID = 2, - VMBUS_EVENT_PORT_ID = 2, - VMBUS_MONITOR_CONNECTION_ID = 3, - VMBUS_MONITOR_PORT_ID = 3, - VMBUS_MESSAGE_SINT = 2, -}; - -/* #defines */ - -#define HV_PRESENT_BIT 0x80000000 - -#define HV_LINUX_GUEST_ID_LO 0x00000000 -#define HV_LINUX_GUEST_ID_HI 0xB16B00B5 -#define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \ - HV_LINUX_GUEST_ID_LO) - -#define HV_CPU_POWER_MANAGEMENT (1 << 0) -#define HV_RECOMMENDATIONS_MAX 4 - -#define HV_X64_MAX 5 -#define HV_CAPS_MAX 8 - - -#define HV_HYPERCALL_PARAM_ALIGN sizeof(u64) - - -/* Service definitions */ - -#define HV_SERVICE_PARENT_PORT (0) -#define HV_SERVICE_PARENT_CONNECTION (0) - -#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS (0) -#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER (1) -#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE (2) -#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED (3) - -#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID (1) -#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID (2) -#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID (3) -#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID (4) -#define HV_SERVICE_MAX_MESSAGE_ID (4) - -#define HV_SERVICE_PROTOCOL_VERSION (0x0010) -#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64 - -/* #define VMBUS_REVISION_NUMBER 6 */ - -/* Our local vmbus's port and connection id. Anything >0 is fine */ -/* #define VMBUS_PORT_ID 11 */ - -/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */ -static const uuid_le VMBUS_SERVICE_ID = { - .b = { - 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, - 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4 - }, -}; - -#define MAX_NUM_CPUS 32 - - -struct hv_input_signal_event_buffer { - u64 align8; - struct hv_input_signal_event event; -}; - -struct hv_context { - /* We only support running on top of Hyper-V - * So at this point this really can only contain the Hyper-V ID - */ - u64 guestid; - - void *hypercall_page; - - bool synic_initialized; - - /* - * This is used as an input param to HvCallSignalEvent hypercall. The - * input param is immutable in our usage and must be dynamic mem (vs - * stack or global). */ - struct hv_input_signal_event_buffer *signal_event_buffer; - /* 8-bytes aligned of the buffer above */ - struct hv_input_signal_event *signal_event_param; - - void *synic_message_page[MAX_NUM_CPUS]; - void *synic_event_page[MAX_NUM_CPUS]; -}; - -extern struct hv_context hv_context; - - -/* Hv Interface */ - -extern int hv_init(void); - -extern void hv_cleanup(void); - -extern u16 hv_post_message(union hv_connection_id connection_id, - enum hv_message_type message_type, - void *payload, size_t payload_size); - -extern u16 hv_signal_event(void); - -extern void hv_synic_init(void *irqarg); - -extern void hv_synic_cleanup(void *arg); - - -/* Interface */ - - -int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer, - u32 buflen); - -void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); - -int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info, - struct scatterlist *sglist, - u32 sgcount); - -int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer, - u32 buflen); - -int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info, - void *buffer, - u32 buflen, - u32 offset); - -u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info); - -void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix); - -void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, - struct hv_ring_buffer_debug_info *debug_info); - -/* - * Maximum channels is determined by the size of the interrupt page - * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt - * and the other is receive endpoint interrupt - */ -#define MAX_NUM_CHANNELS ((PAGE_SIZE >> 1) << 3) /* 16348 channels */ - -/* The value here must be in multiple of 32 */ -/* TODO: Need to make this configurable */ -#define MAX_NUM_CHANNELS_SUPPORTED 256 - - -enum vmbus_connect_state { - DISCONNECTED, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -#define MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT - -struct vmbus_connection { - enum vmbus_connect_state conn_state; - - atomic_t next_gpadl_handle; - - /* - * Represents channel interrupts. Each bit position represents a - * channel. When a channel sends an interrupt via VMBUS, it finds its - * bit in the sendInterruptPage, set it and calls Hv to generate a port - * event. The other end receives the port event and parse the - * recvInterruptPage to see which bit is set - */ - void *int_page; - void *send_int_page; - void *recv_int_page; - - /* - * 2 pages - 1st page for parent->child notification and 2nd - * is child->parent notification - */ - void *monitor_pages; - struct list_head chn_msg_list; - spinlock_t channelmsg_lock; - - /* List of channels */ - struct list_head chn_list; - spinlock_t channel_lock; - - struct workqueue_struct *work_queue; -}; - - -struct vmbus_msginfo { - /* Bookkeeping stuff */ - struct list_head msglist_entry; - - /* The message itself */ - unsigned char msg[0]; -}; - - -extern struct vmbus_connection vmbus_connection; - -/* General vmbus interface */ - -struct hv_device *vmbus_device_create(uuid_le *type, - uuid_le *instance, - struct vmbus_channel *channel); - -int vmbus_device_register(struct hv_device *child_device_obj); -void vmbus_device_unregister(struct hv_device *device_obj); - -/* static void */ -/* VmbusChildDeviceDestroy( */ -/* struct hv_device *); */ - -struct vmbus_channel *relid2channel(u32 relid); - - -/* Connection interface */ - -int vmbus_connect(void); - -int vmbus_post_msg(void *buffer, size_t buflen); - -int vmbus_set_event(u32 child_relid); - -void vmbus_on_event(unsigned long data); - - -#endif /* _HYPERV_VMBUS_H */ diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c deleted file mode 100644 index 70e2e66..0000000 --- a/drivers/staging/hv/ring_buffer.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - - -/* #defines */ - - -/* Amount of space to write to */ -#define BYTES_AVAIL_TO_WRITE(r, w, z) \ - ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) - - -/* - * - * hv_get_ringbuffer_availbytes() - * - * Get number of bytes available to read and to write to - * for the specified ring buffer - */ -static inline void -hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, - u32 *read, u32 *write) -{ - u32 read_loc, write_loc; - - smp_read_barrier_depends(); - - /* Capture the read/write indices before they changed */ - read_loc = rbi->ring_buffer->read_index; - write_loc = rbi->ring_buffer->write_index; - - *write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize); - *read = rbi->ring_datasize - *write; -} - -/* - * hv_get_next_write_location() - * - * Get the next write location for the specified ring buffer - * - */ -static inline u32 -hv_get_next_write_location(struct hv_ring_buffer_info *ring_info) -{ - u32 next = ring_info->ring_buffer->write_index; - - return next; -} - -/* - * hv_set_next_write_location() - * - * Set the next write location for the specified ring buffer - * - */ -static inline void -hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, - u32 next_write_location) -{ - ring_info->ring_buffer->write_index = next_write_location; -} - -/* - * hv_get_next_read_location() - * - * Get the next read location for the specified ring buffer - */ -static inline u32 -hv_get_next_read_location(struct hv_ring_buffer_info *ring_info) -{ - u32 next = ring_info->ring_buffer->read_index; - - return next; -} - -/* - * hv_get_next_readlocation_withoffset() - * - * Get the next read location + offset for the specified ring buffer. - * This allows the caller to skip - */ -static inline u32 -hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info, - u32 offset) -{ - u32 next = ring_info->ring_buffer->read_index; - - next += offset; - next %= ring_info->ring_datasize; - - return next; -} - -/* - * - * hv_set_next_read_location() - * - * Set the next read location for the specified ring buffer - * - */ -static inline void -hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, - u32 next_read_location) -{ - ring_info->ring_buffer->read_index = next_read_location; -} - - -/* - * - * hv_get_ring_buffer() - * - * Get the start of the ring buffer - */ -static inline void * -hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info) -{ - return (void *)ring_info->ring_buffer->buffer; -} - - -/* - * - * hv_get_ring_buffersize() - * - * Get the size of the ring buffer - */ -static inline u32 -hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info) -{ - return ring_info->ring_datasize; -} - -/* - * - * hv_get_ring_bufferindices() - * - * Get the read and write indices as u64 of the specified ring buffer - * - */ -static inline u64 -hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) -{ - return (u64)ring_info->ring_buffer->write_index << 32; -} - - -/* - * - * hv_dump_ring_info() - * - * Dump out to console the ring buffer info - * - */ -void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix) -{ - u32 bytes_avail_towrite; - u32 bytes_avail_toread; - - hv_get_ringbuffer_availbytes(ring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - DPRINT(VMBUS, - DEBUG_RING_LVL, - "%s <>", - prefix, - ring_info, - ring_info->ring_buffer->buffer, - bytes_avail_towrite, - bytes_avail_toread, - ring_info->ring_buffer->read_index, - ring_info->ring_buffer->write_index); -} - - -/* - * - * hv_copyfrom_ringbuffer() - * - * Helper routine to copy to source from ring buffer. - * Assume there is enough room. Handles wrap-around in src case only!! - * - */ -static u32 hv_copyfrom_ringbuffer( - struct hv_ring_buffer_info *ring_info, - void *dest, - u32 destlen, - u32 start_read_offset) -{ - void *ring_buffer = hv_get_ring_buffer(ring_info); - u32 ring_buffer_size = hv_get_ring_buffersize(ring_info); - - u32 frag_len; - - /* wrap-around detected at the src */ - if (destlen > ring_buffer_size - start_read_offset) { - frag_len = ring_buffer_size - start_read_offset; - - memcpy(dest, ring_buffer + start_read_offset, frag_len); - memcpy(dest + frag_len, ring_buffer, destlen - frag_len); - } else - - memcpy(dest, ring_buffer + start_read_offset, destlen); - - - start_read_offset += destlen; - start_read_offset %= ring_buffer_size; - - return start_read_offset; -} - - -/* - * - * hv_copyto_ringbuffer() - * - * Helper routine to copy from source to ring buffer. - * Assume there is enough room. Handles wrap-around in dest case only!! - * - */ -static u32 hv_copyto_ringbuffer( - struct hv_ring_buffer_info *ring_info, - u32 start_write_offset, - void *src, - u32 srclen) -{ - void *ring_buffer = hv_get_ring_buffer(ring_info); - u32 ring_buffer_size = hv_get_ring_buffersize(ring_info); - u32 frag_len; - - /* wrap-around detected! */ - if (srclen > ring_buffer_size - start_write_offset) { - frag_len = ring_buffer_size - start_write_offset; - memcpy(ring_buffer + start_write_offset, src, frag_len); - memcpy(ring_buffer, src + frag_len, srclen - frag_len); - } else - memcpy(ring_buffer + start_write_offset, src, srclen); - - start_write_offset += srclen; - start_write_offset %= ring_buffer_size; - - return start_write_offset; -} - -/* - * - * hv_ringbuffer_get_debuginfo() - * - * Get various debug metrics for the specified ring buffer - * - */ -void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, - struct hv_ring_buffer_debug_info *debug_info) -{ - u32 bytes_avail_towrite; - u32 bytes_avail_toread; - - if (ring_info->ring_buffer) { - hv_get_ringbuffer_availbytes(ring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - debug_info->bytes_avail_toread = bytes_avail_toread; - debug_info->bytes_avail_towrite = bytes_avail_towrite; - debug_info->current_read_index = - ring_info->ring_buffer->read_index; - debug_info->current_write_index = - ring_info->ring_buffer->write_index; - debug_info->current_interrupt_mask = - ring_info->ring_buffer->interrupt_mask; - } -} - - -/* - * - * hv_get_ringbuffer_interrupt_mask() - * - * Get the interrupt mask for the specified ring buffer - * - */ -u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *rbi) -{ - return rbi->ring_buffer->interrupt_mask; -} - -/* - * - * hv_ringbuffer_init() - * - *Initialize the ring buffer - * - */ -int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, - void *buffer, u32 buflen) -{ - if (sizeof(struct hv_ring_buffer) != PAGE_SIZE) - return -EINVAL; - - memset(ring_info, 0, sizeof(struct hv_ring_buffer_info)); - - ring_info->ring_buffer = (struct hv_ring_buffer *)buffer; - ring_info->ring_buffer->read_index = - ring_info->ring_buffer->write_index = 0; - - ring_info->ring_size = buflen; - ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer); - - spin_lock_init(&ring_info->ring_lock); - - return 0; -} - -/* - * - * hv_ringbuffer_cleanup() - * - * Cleanup the ring buffer - * - */ -void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) -{ -} - -/* - * - * hv_ringbuffer_write() - * - * Write to the ring buffer - * - */ -int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, - struct scatterlist *sglist, u32 sgcount) -{ - int i = 0; - u32 bytes_avail_towrite; - u32 bytes_avail_toread; - u32 totalbytes_towrite = 0; - - struct scatterlist *sg; - u32 next_write_location; - u64 prev_indices = 0; - unsigned long flags; - - for_each_sg(sglist, sg, sgcount, i) - { - totalbytes_towrite += sg->length; - } - - totalbytes_towrite += sizeof(u64); - - spin_lock_irqsave(&outring_info->ring_lock, flags); - - hv_get_ringbuffer_availbytes(outring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - - /* If there is only room for the packet, assume it is full. */ - /* Otherwise, the next time around, we think the ring buffer */ - /* is empty since the read index == write index */ - if (bytes_avail_towrite <= totalbytes_towrite) { - spin_unlock_irqrestore(&outring_info->ring_lock, flags); - return -EAGAIN; - } - - /* Write to the ring buffer */ - next_write_location = hv_get_next_write_location(outring_info); - - for_each_sg(sglist, sg, sgcount, i) - { - next_write_location = hv_copyto_ringbuffer(outring_info, - next_write_location, - sg_virt(sg), - sg->length); - } - - /* Set previous packet start */ - prev_indices = hv_get_ring_bufferindices(outring_info); - - next_write_location = hv_copyto_ringbuffer(outring_info, - next_write_location, - &prev_indices, - sizeof(u64)); - - /* Make sure we flush all writes before updating the writeIndex */ - smp_wmb(); - - /* Now, update the write location */ - hv_set_next_write_location(outring_info, next_write_location); - - - spin_unlock_irqrestore(&outring_info->ring_lock, flags); - return 0; -} - - -/* - * - * hv_ringbuffer_peek() - * - * Read without advancing the read index - * - */ -int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info, - void *Buffer, u32 buflen) -{ - u32 bytes_avail_towrite; - u32 bytes_avail_toread; - u32 next_read_location = 0; - unsigned long flags; - - spin_lock_irqsave(&Inring_info->ring_lock, flags); - - hv_get_ringbuffer_availbytes(Inring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - /* Make sure there is something to read */ - if (bytes_avail_toread < buflen) { - - spin_unlock_irqrestore(&Inring_info->ring_lock, flags); - - return -EAGAIN; - } - - /* Convert to byte offset */ - next_read_location = hv_get_next_read_location(Inring_info); - - next_read_location = hv_copyfrom_ringbuffer(Inring_info, - Buffer, - buflen, - next_read_location); - - spin_unlock_irqrestore(&Inring_info->ring_lock, flags); - - return 0; -} - - -/* - * - * hv_ringbuffer_read() - * - * Read and advance the read index - * - */ -int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, - u32 buflen, u32 offset) -{ - u32 bytes_avail_towrite; - u32 bytes_avail_toread; - u32 next_read_location = 0; - u64 prev_indices = 0; - unsigned long flags; - - if (buflen <= 0) - return -EINVAL; - - spin_lock_irqsave(&inring_info->ring_lock, flags); - - hv_get_ringbuffer_availbytes(inring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - /* Make sure there is something to read */ - if (bytes_avail_toread < buflen) { - spin_unlock_irqrestore(&inring_info->ring_lock, flags); - - return -EAGAIN; - } - - next_read_location = - hv_get_next_readlocation_withoffset(inring_info, offset); - - next_read_location = hv_copyfrom_ringbuffer(inring_info, - buffer, - buflen, - next_read_location); - - next_read_location = hv_copyfrom_ringbuffer(inring_info, - &prev_indices, - sizeof(u64), - next_read_location); - - /* Make sure all reads are done before we update the read index since */ - /* the writer may start writing to the read area once the read index */ - /*is updated */ - smp_mb(); - - /* Update the read index */ - hv_set_next_read_location(inring_info, next_read_location); - - spin_unlock_irqrestore(&inring_info->ring_lock, flags); - - return 0; -} diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index e412716..af185ab 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include #include -#include "hyperv.h" #define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c deleted file mode 100644 index 11224ed..0000000 --- a/drivers/staging/hv/tools/hv_kvp_daemon.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * An implementation of key value pair (KVP) functionality for Linux. - * - * - * Copyright (C) 2010, Novell, Inc. - * Author : K. Y. Srinivasan - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * KYS: TODO. Need to register these in the kernel. - * - * The following definitions are shared with the in-kernel component; do not - * change any of this without making the corresponding changes in - * the KVP kernel component. - */ -#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */ -#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ -#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ - -/* - * KVP protocol: The user mode component first registers with the - * the kernel component. Subsequently, the kernel component requests, data - * for the specified keys. In response to this message the user mode component - * fills in the value corresponding to the specified key. We overload the - * sequence field in the cn_msg header to define our KVP message types. - * - * We use this infrastructure for also supporting queries from user mode - * application for state that may be maintained in the KVP kernel component. - * - * XXXKYS: Have a shared header file between the user and kernel (TODO) - */ - -enum kvp_op { - KVP_REGISTER = 0, /* Register the user mode component*/ - KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/ - KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/ - KVP_USER_GET, /*User is requesting the value for the specified key*/ - KVP_USER_SET /*User is providing the value for the specified key*/ -}; - -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512 -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048 - -struct hv_ku_msg { - __u32 kvp_index; - __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ - __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ -}; - -enum key_index { - FullyQualifiedDomainName = 0, - IntegrationServicesVersion, /*This key is serviced in the kernel*/ - NetworkAddressIPv4, - NetworkAddressIPv6, - OSBuildNumber, - OSName, - OSMajorVersion, - OSMinorVersion, - OSVersion, - ProcessorArchitecture -}; - -/* - * End of shared definitions. - */ - -static char kvp_send_buffer[4096]; -static char kvp_recv_buffer[4096]; -static struct sockaddr_nl addr; - -static char *os_name = ""; -static char *os_major = ""; -static char *os_minor = ""; -static char *processor_arch; -static char *os_build; -static char *lic_version; -static struct utsname uts_buf; - -void kvp_get_os_info(void) -{ - FILE *file; - char *p, buf[512]; - - uname(&uts_buf); - os_build = uts_buf.release; - processor_arch = uts_buf.machine; - - /* - * The current windows host (win7) expects the build - * string to be of the form: x.y.z - * Strip additional information we may have. - */ - p = strchr(os_build, '-'); - if (p) - *p = '\0'; - - file = fopen("/etc/SuSE-release", "r"); - if (file != NULL) - goto kvp_osinfo_found; - file = fopen("/etc/redhat-release", "r"); - if (file != NULL) - goto kvp_osinfo_found; - /* - * Add code for other supported platforms. - */ - - /* - * We don't have information about the os. - */ - os_name = uts_buf.sysname; - return; - -kvp_osinfo_found: - /* up to three lines */ - p = fgets(buf, sizeof(buf), file); - if (p) { - p = strchr(buf, '\n'); - if (p) - *p = '\0'; - p = strdup(buf); - if (!p) - goto done; - os_name = p; - - /* second line */ - p = fgets(buf, sizeof(buf), file); - if (p) { - p = strchr(buf, '\n'); - if (p) - *p = '\0'; - p = strdup(buf); - if (!p) - goto done; - os_major = p; - - /* third line */ - p = fgets(buf, sizeof(buf), file); - if (p) { - p = strchr(buf, '\n'); - if (p) - *p = '\0'; - p = strdup(buf); - if (p) - os_minor = p; - } - } - } - -done: - fclose(file); - return; -} - -static int -kvp_get_ip_address(int family, char *buffer, int length) -{ - struct ifaddrs *ifap; - struct ifaddrs *curp; - int ipv4_len = strlen("255.255.255.255") + 1; - int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1; - int offset = 0; - const char *str; - char tmp[50]; - int error = 0; - - /* - * On entry into this function, the buffer is capable of holding the - * maximum key value (2048 bytes). - */ - - if (getifaddrs(&ifap)) { - strcpy(buffer, "getifaddrs failed\n"); - return 1; - } - - curp = ifap; - while (curp != NULL) { - if ((curp->ifa_addr != NULL) && - (curp->ifa_addr->sa_family == family)) { - if (family == AF_INET) { - struct sockaddr_in *addr = - (struct sockaddr_in *) curp->ifa_addr; - - str = inet_ntop(family, &addr->sin_addr, - tmp, 50); - if (str == NULL) { - strcpy(buffer, "inet_ntop failed\n"); - error = 1; - goto getaddr_done; - } - if (offset == 0) - strcpy(buffer, tmp); - else - strcat(buffer, tmp); - strcat(buffer, ";"); - - offset += strlen(str) + 1; - if ((length - offset) < (ipv4_len + 1)) - goto getaddr_done; - - } else { - - /* - * We only support AF_INET and AF_INET6 - * and the list of addresses is separated by a ";". - */ - struct sockaddr_in6 *addr = - (struct sockaddr_in6 *) curp->ifa_addr; - - str = inet_ntop(family, - &addr->sin6_addr.s6_addr, - tmp, 50); - if (str == NULL) { - strcpy(buffer, "inet_ntop failed\n"); - error = 1; - goto getaddr_done; - } - if (offset == 0) - strcpy(buffer, tmp); - else - strcat(buffer, tmp); - strcat(buffer, ";"); - offset += strlen(str) + 1; - if ((length - offset) < (ipv6_len + 1)) - goto getaddr_done; - - } - - } - curp = curp->ifa_next; - } - -getaddr_done: - freeifaddrs(ifap); - return error; -} - - -static int -kvp_get_domain_name(char *buffer, int length) -{ - struct addrinfo hints, *info ; - int error = 0; - - gethostname(buffer, length); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - - error = getaddrinfo(buffer, NULL, &hints, &info); - if (error != 0) { - strcpy(buffer, "getaddrinfo failed\n"); - return error; - } - strcpy(buffer, info->ai_canonname); - freeaddrinfo(info); - return error; -} - -static int -netlink_send(int fd, struct cn_msg *msg) -{ - struct nlmsghdr *nlh; - unsigned int size; - struct msghdr message; - char buffer[64]; - struct iovec iov[2]; - - size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); - - nlh = (struct nlmsghdr *)buffer; - nlh->nlmsg_seq = 0; - nlh->nlmsg_pid = getpid(); - nlh->nlmsg_type = NLMSG_DONE; - nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); - nlh->nlmsg_flags = 0; - - iov[0].iov_base = nlh; - iov[0].iov_len = sizeof(*nlh); - - iov[1].iov_base = msg; - iov[1].iov_len = size; - - memset(&message, 0, sizeof(message)); - message.msg_name = &addr; - message.msg_namelen = sizeof(addr); - message.msg_iov = iov; - message.msg_iovlen = 2; - - return sendmsg(fd, &message, 0); -} - -int main(void) -{ - int fd, len, sock_opt; - int error; - struct cn_msg *message; - struct pollfd pfd; - struct nlmsghdr *incoming_msg; - struct cn_msg *incoming_cn_msg; - struct hv_ku_msg *hv_msg; - char *p; - char *key_value; - char *key_name; - - daemon(1, 0); - openlog("KVP", 0, LOG_USER); - syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); - /* - * Retrieve OS release information. - */ - kvp_get_os_info(); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); - if (fd < 0) { - syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(-1); - } - addr.nl_family = AF_NETLINK; - addr.nl_pad = 0; - addr.nl_pid = 0; - addr.nl_groups = CN_KVP_IDX; - - - error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); - if (error < 0) { - syslog(LOG_ERR, "bind failed; error:%d", error); - close(fd); - exit(-1); - } - sock_opt = addr.nl_groups; - setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); - /* - * Register ourselves with the kernel. - */ - message = (struct cn_msg *)kvp_send_buffer; - message->id.idx = CN_KVP_IDX; - message->id.val = CN_KVP_VAL; - message->seq = KVP_REGISTER; - message->ack = 0; - message->len = 0; - - len = netlink_send(fd, message); - if (len < 0) { - syslog(LOG_ERR, "netlink_send failed; error:%d", len); - close(fd); - exit(-1); - } - - pfd.fd = fd; - - while (1) { - pfd.events = POLLIN; - pfd.revents = 0; - poll(&pfd, 1, -1); - - len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0); - - if (len < 0) { - syslog(LOG_ERR, "recv failed; error:%d", len); - close(fd); - return -1; - } - - incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; - incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); - - switch (incoming_cn_msg->seq) { - case KVP_REGISTER: - /* - * Driver is registering with us; stash away the version - * information. - */ - p = (char *)incoming_cn_msg->data; - lic_version = malloc(strlen(p) + 1); - if (lic_version) { - strcpy(lic_version, p); - syslog(LOG_INFO, "KVP LIC Version: %s", - lic_version); - } else { - syslog(LOG_ERR, "malloc failed"); - } - continue; - - case KVP_KERNEL_GET: - break; - default: - continue; - } - - hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data; - key_name = (char *)hv_msg->kvp_key; - key_value = (char *)hv_msg->kvp_value; - - switch (hv_msg->kvp_index) { - case FullyQualifiedDomainName: - kvp_get_domain_name(key_value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "FullyQualifiedDomainName"); - break; - case IntegrationServicesVersion: - strcpy(key_name, "IntegrationServicesVersion"); - strcpy(key_value, lic_version); - break; - case NetworkAddressIPv4: - kvp_get_ip_address(AF_INET, key_value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "NetworkAddressIPv4"); - break; - case NetworkAddressIPv6: - kvp_get_ip_address(AF_INET6, key_value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "NetworkAddressIPv6"); - break; - case OSBuildNumber: - strcpy(key_value, os_build); - strcpy(key_name, "OSBuildNumber"); - break; - case OSName: - strcpy(key_value, os_name); - strcpy(key_name, "OSName"); - break; - case OSMajorVersion: - strcpy(key_value, os_major); - strcpy(key_name, "OSMajorVersion"); - break; - case OSMinorVersion: - strcpy(key_value, os_minor); - strcpy(key_name, "OSMinorVersion"); - break; - case OSVersion: - strcpy(key_value, os_build); - strcpy(key_name, "OSVersion"); - break; - case ProcessorArchitecture: - strcpy(key_value, processor_arch); - strcpy(key_name, "ProcessorArchitecture"); - break; - default: - strcpy(key_value, "Unknown Key"); - /* - * We use a null key name to terminate enumeration. - */ - strcpy(key_name, ""); - break; - } - /* - * Send the value back to the kernel. The response is - * already in the receive buffer. Update the cn_msg header to - * reflect the key value that has been added to the message - */ - - incoming_cn_msg->id.idx = CN_KVP_IDX; - incoming_cn_msg->id.val = CN_KVP_VAL; - incoming_cn_msg->seq = KVP_USER_SET; - incoming_cn_msg->ack = 0; - incoming_cn_msg->len = sizeof(struct hv_ku_msg); - - len = netlink_send(fd, incoming_cn_msg); - if (len < 0) { - syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(-1); - } - } - -} diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c deleted file mode 100644 index d2562af..0000000 --- a/drivers/staging/hv/vmbus_drv.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_vmbus.h" - - -static struct acpi_device *hv_acpi_dev; - -static struct tasklet_struct msg_dpc; -static struct tasklet_struct event_dpc; - -unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL); -EXPORT_SYMBOL(vmbus_loglevel); - -static struct completion probe_event; -static int irq; - -static void get_channel_info(struct hv_device *device, - struct hv_device_info *info) -{ - struct vmbus_channel_debug_info debug_info; - - if (!device->channel) - return; - - vmbus_get_debug_info(device->channel, &debug_info); - - info->chn_id = debug_info.relid; - info->chn_state = debug_info.state; - memcpy(&info->chn_type, &debug_info.interfacetype, - sizeof(uuid_le)); - memcpy(&info->chn_instance, &debug_info.interface_instance, - sizeof(uuid_le)); - - info->monitor_id = debug_info.monitorid; - - info->server_monitor_pending = debug_info.servermonitor_pending; - info->server_monitor_latency = debug_info.servermonitor_latency; - info->server_monitor_conn_id = debug_info.servermonitor_connectionid; - - info->client_monitor_pending = debug_info.clientmonitor_pending; - info->client_monitor_latency = debug_info.clientmonitor_latency; - info->client_monitor_conn_id = debug_info.clientmonitor_connectionid; - - info->inbound.int_mask = debug_info.inbound.current_interrupt_mask; - info->inbound.read_idx = debug_info.inbound.current_read_index; - info->inbound.write_idx = debug_info.inbound.current_write_index; - info->inbound.bytes_avail_toread = - debug_info.inbound.bytes_avail_toread; - info->inbound.bytes_avail_towrite = - debug_info.inbound.bytes_avail_towrite; - - info->outbound.int_mask = - debug_info.outbound.current_interrupt_mask; - info->outbound.read_idx = debug_info.outbound.current_read_index; - info->outbound.write_idx = debug_info.outbound.current_write_index; - info->outbound.bytes_avail_toread = - debug_info.outbound.bytes_avail_toread; - info->outbound.bytes_avail_towrite = - debug_info.outbound.bytes_avail_towrite; -} - -#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2) -static void print_alias_name(struct hv_device *hv_dev, char *alias_name) -{ - int i; - for (i = 0; i < VMBUS_ALIAS_LEN; i += 2) - sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); -} - -/* - * vmbus_show_device_attr - Show the device attribute in sysfs. - * - * This is invoked when user does a - * "cat /sys/bus/vmbus/devices//" - */ -static ssize_t vmbus_show_device_attr(struct device *dev, - struct device_attribute *dev_attr, - char *buf) -{ - struct hv_device *hv_dev = device_to_hv_device(dev); - struct hv_device_info *device_info; - char alias_name[VMBUS_ALIAS_LEN + 1]; - int ret = 0; - - device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL); - if (!device_info) - return ret; - - get_channel_info(hv_dev, device_info); - - if (!strcmp(dev_attr->attr.name, "class_id")) { - ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info->chn_type.b[3], - device_info->chn_type.b[2], - device_info->chn_type.b[1], - device_info->chn_type.b[0], - device_info->chn_type.b[5], - device_info->chn_type.b[4], - device_info->chn_type.b[7], - device_info->chn_type.b[6], - device_info->chn_type.b[8], - device_info->chn_type.b[9], - device_info->chn_type.b[10], - device_info->chn_type.b[11], - device_info->chn_type.b[12], - device_info->chn_type.b[13], - device_info->chn_type.b[14], - device_info->chn_type.b[15]); - } else if (!strcmp(dev_attr->attr.name, "device_id")) { - ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x%02x%02x}\n", - device_info->chn_instance.b[3], - device_info->chn_instance.b[2], - device_info->chn_instance.b[1], - device_info->chn_instance.b[0], - device_info->chn_instance.b[5], - device_info->chn_instance.b[4], - device_info->chn_instance.b[7], - device_info->chn_instance.b[6], - device_info->chn_instance.b[8], - device_info->chn_instance.b[9], - device_info->chn_instance.b[10], - device_info->chn_instance.b[11], - device_info->chn_instance.b[12], - device_info->chn_instance.b[13], - device_info->chn_instance.b[14], - device_info->chn_instance.b[15]); - } else if (!strcmp(dev_attr->attr.name, "modalias")) { - print_alias_name(hv_dev, alias_name); - ret = sprintf(buf, "vmbus:%s\n", alias_name); - } else if (!strcmp(dev_attr->attr.name, "state")) { - ret = sprintf(buf, "%d\n", device_info->chn_state); - } else if (!strcmp(dev_attr->attr.name, "id")) { - ret = sprintf(buf, "%d\n", device_info->chn_id); - } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { - ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); - } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { - ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); - } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { - ret = sprintf(buf, "%d\n", device_info->outbound.write_idx); - } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { - ret = sprintf(buf, "%d\n", - device_info->outbound.bytes_avail_toread); - } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) { - ret = sprintf(buf, "%d\n", - device_info->outbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { - ret = sprintf(buf, "%d\n", device_info->inbound.int_mask); - } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { - ret = sprintf(buf, "%d\n", device_info->inbound.read_idx); - } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { - ret = sprintf(buf, "%d\n", device_info->inbound.write_idx); - } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { - ret = sprintf(buf, "%d\n", - device_info->inbound.bytes_avail_toread); - } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { - ret = sprintf(buf, "%d\n", - device_info->inbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { - ret = sprintf(buf, "%d\n", device_info->monitor_id); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { - ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { - ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { - ret = sprintf(buf, "%d\n", - device_info->server_monitor_conn_id); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { - ret = sprintf(buf, "%d\n", device_info->client_monitor_pending); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { - ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { - ret = sprintf(buf, "%d\n", - device_info->client_monitor_conn_id); - } - - kfree(device_info); - return ret; -} - -/* Set up per device attributes in /sys/bus/vmbus/devices/ */ -static struct device_attribute vmbus_device_attrs[] = { - __ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL), - - __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - - __ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - - __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL), - - __ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR_NULL -}; - - -/* - * vmbus_uevent - add uevent for our device - * - * This routine is invoked when a device is added or removed on the vmbus to - * generate a uevent to udev in the userspace. The udev will then look at its - * rule and the uevent generated here to load the appropriate driver - * - * The alias string will be of the form vmbus:guid where guid is the string - * representation of the device guid (each byte of the guid will be - * represented with two hex characters. - */ -static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) -{ - struct hv_device *dev = device_to_hv_device(device); - int ret; - char alias_name[VMBUS_ALIAS_LEN + 1]; - - print_alias_name(dev, alias_name); - ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name); - return ret; -} - -static uuid_le null_guid; - -static inline bool is_null_guid(const __u8 *guid) -{ - if (memcmp(guid, &null_guid, sizeof(uuid_le))) - return false; - return true; -} - -/* - * Return a matching hv_vmbus_device_id pointer. - * If there is no match, return NULL. - */ -static const struct hv_vmbus_device_id *hv_vmbus_get_id( - const struct hv_vmbus_device_id *id, - __u8 *guid) -{ - for (; !is_null_guid(id->guid); id++) - if (!memcmp(&id->guid, guid, sizeof(uuid_le))) - return id; - - return NULL; -} - - - -/* - * vmbus_match - Attempt to match the specified device to the specified driver - */ -static int vmbus_match(struct device *device, struct device_driver *driver) -{ - struct hv_driver *drv = drv_to_hv_drv(driver); - struct hv_device *hv_dev = device_to_hv_device(device); - - if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b)) - return 1; - - return 0; -} - -/* - * vmbus_probe - Add the new vmbus's child device - */ -static int vmbus_probe(struct device *child_device) -{ - int ret = 0; - struct hv_driver *drv = - drv_to_hv_drv(child_device->driver); - struct hv_device *dev = device_to_hv_device(child_device); - const struct hv_vmbus_device_id *dev_id; - - dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b); - if (drv->probe) { - ret = drv->probe(dev, dev_id); - if (ret != 0) - pr_err("probe failed for device %s (%d)\n", - dev_name(child_device), ret); - - } else { - pr_err("probe not set for driver %s\n", - dev_name(child_device)); - ret = -ENODEV; - } - return ret; -} - -/* - * vmbus_remove - Remove a vmbus device - */ -static int vmbus_remove(struct device *child_device) -{ - struct hv_driver *drv = drv_to_hv_drv(child_device->driver); - struct hv_device *dev = device_to_hv_device(child_device); - - if (drv->remove) - drv->remove(dev); - else - pr_err("remove not set for driver %s\n", - dev_name(child_device)); - - return 0; -} - - -/* - * vmbus_shutdown - Shutdown a vmbus device - */ -static void vmbus_shutdown(struct device *child_device) -{ - struct hv_driver *drv; - struct hv_device *dev = device_to_hv_device(child_device); - - - /* The device may not be attached yet */ - if (!child_device->driver) - return; - - drv = drv_to_hv_drv(child_device->driver); - - if (drv->shutdown) - drv->shutdown(dev); - - return; -} - - -/* - * vmbus_device_release - Final callback release of the vmbus child device - */ -static void vmbus_device_release(struct device *device) -{ - struct hv_device *hv_dev = device_to_hv_device(device); - - kfree(hv_dev); - -} - -/* The one and only one */ -static struct bus_type hv_bus = { - .name = "vmbus", - .match = vmbus_match, - .shutdown = vmbus_shutdown, - .remove = vmbus_remove, - .probe = vmbus_probe, - .uevent = vmbus_uevent, - .dev_attrs = vmbus_device_attrs, -}; - -static const char *driver_name = "hyperv"; - - -struct onmessage_work_context { - struct work_struct work; - struct hv_message msg; -}; - -static void vmbus_onmessage_work(struct work_struct *work) -{ - struct onmessage_work_context *ctx; - - ctx = container_of(work, struct onmessage_work_context, - work); - vmbus_onmessage(&ctx->msg); - kfree(ctx); -} - -static void vmbus_on_msg_dpc(unsigned long data) -{ - int cpu = smp_processor_id(); - void *page_addr = hv_context.synic_message_page[cpu]; - struct hv_message *msg = (struct hv_message *)page_addr + - VMBUS_MESSAGE_SINT; - struct onmessage_work_context *ctx; - - while (1) { - if (msg->header.message_type == HVMSG_NONE) { - /* no msg */ - break; - } else { - ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); - if (ctx == NULL) - continue; - INIT_WORK(&ctx->work, vmbus_onmessage_work); - memcpy(&ctx->msg, msg, sizeof(*msg)); - queue_work(vmbus_connection.work_queue, &ctx->work); - } - - msg->header.message_type = HVMSG_NONE; - - /* - * Make sure the write to MessageType (ie set to - * HVMSG_NONE) happens before we read the - * MessagePending and EOMing. Otherwise, the EOMing - * will not deliver any more messages since there is - * no empty slot - */ - smp_mb(); - - if (msg->header.message_flags.msg_pending) { - /* - * This will cause message queue rescan to - * possibly deliver another msg from the - * hypervisor - */ - wrmsrl(HV_X64_MSR_EOM, 0); - } - } -} - -static irqreturn_t vmbus_isr(int irq, void *dev_id) -{ - int cpu = smp_processor_id(); - void *page_addr; - struct hv_message *msg; - union hv_synic_event_flags *event; - bool handled = false; - - /* - * Check for events before checking for messages. This is the order - * in which events and messages are checked in Windows guests on - * Hyper-V, and the Windows team suggested we do the same. - */ - - page_addr = hv_context.synic_event_page[cpu]; - event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; - - /* Since we are a child, we only need to check bit 0 */ - if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { - handled = true; - tasklet_schedule(&event_dpc); - } - - page_addr = hv_context.synic_message_page[cpu]; - msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; - - /* Check if there are actual msgs to be processed */ - if (msg->header.message_type != HVMSG_NONE) { - handled = true; - tasklet_schedule(&msg_dpc); - } - - if (handled) - return IRQ_HANDLED; - else - return IRQ_NONE; -} - -/* - * vmbus_bus_init -Main vmbus driver initialization routine. - * - * Here, we - * - initialize the vmbus driver context - * - invoke the vmbus hv main init routine - * - get the irq resource - * - retrieve the channel offers - */ -static int vmbus_bus_init(int irq) -{ - int ret; - unsigned int vector; - - /* Hypervisor initialization...setup hypercall page..etc */ - ret = hv_init(); - if (ret != 0) { - pr_err("Unable to initialize the hypervisor - 0x%x\n", ret); - return ret; - } - - tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0); - tasklet_init(&event_dpc, vmbus_on_event, 0); - - ret = bus_register(&hv_bus); - if (ret) - goto err_cleanup; - - ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, - driver_name, hv_acpi_dev); - - if (ret != 0) { - pr_err("Unable to request IRQ %d\n", - irq); - goto err_unregister; - } - - vector = IRQ0_VECTOR + irq; - - /* - * Notify the hypervisor of our irq and - * connect to the host. - */ - on_each_cpu(hv_synic_init, (void *)&vector, 1); - ret = vmbus_connect(); - if (ret) - goto err_irq; - - vmbus_request_offers(); - - return 0; - -err_irq: - free_irq(irq, hv_acpi_dev); - -err_unregister: - bus_unregister(&hv_bus); - -err_cleanup: - hv_cleanup(); - - return ret; -} - -/** - * __vmbus_child_driver_register - Register a vmbus's driver - * @drv: Pointer to driver structure you want to register - * @owner: owner module of the drv - * @mod_name: module name string - * - * Registers the given driver with Linux through the 'driver_register()' call - * and sets up the hyper-v vmbus handling for this driver. - * It will return the state of the 'driver_register()' call. - * - */ -int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name) -{ - int ret; - - pr_info("registering driver %s\n", hv_driver->name); - - hv_driver->driver.name = hv_driver->name; - hv_driver->driver.owner = owner; - hv_driver->driver.mod_name = mod_name; - hv_driver->driver.bus = &hv_bus; - - ret = driver_register(&hv_driver->driver); - - vmbus_request_offers(); - - return ret; -} -EXPORT_SYMBOL_GPL(__vmbus_driver_register); - -/** - * vmbus_driver_unregister() - Unregister a vmbus's driver - * @drv: Pointer to driver structure you want to un-register - * - * Un-register the given driver that was previous registered with a call to - * vmbus_driver_register() - */ -void vmbus_driver_unregister(struct hv_driver *hv_driver) -{ - pr_info("unregistering driver %s\n", hv_driver->name); - - driver_unregister(&hv_driver->driver); - -} -EXPORT_SYMBOL_GPL(vmbus_driver_unregister); - -/* - * vmbus_device_create - Creates and registers a new child device - * on the vmbus. - */ -struct hv_device *vmbus_device_create(uuid_le *type, - uuid_le *instance, - struct vmbus_channel *channel) -{ - struct hv_device *child_device_obj; - - child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL); - if (!child_device_obj) { - pr_err("Unable to allocate device object for child device\n"); - return NULL; - } - - child_device_obj->channel = channel; - memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le)); - memcpy(&child_device_obj->dev_instance, instance, - sizeof(uuid_le)); - - - return child_device_obj; -} - -/* - * vmbus_device_register - Register the child device - */ -int vmbus_device_register(struct hv_device *child_device_obj) -{ - int ret = 0; - - static atomic_t device_num = ATOMIC_INIT(0); - - dev_set_name(&child_device_obj->device, "vmbus_0_%d", - atomic_inc_return(&device_num)); - - child_device_obj->device.bus = &hv_bus; - child_device_obj->device.parent = &hv_acpi_dev->dev; - child_device_obj->device.release = vmbus_device_release; - - /* - * Register with the LDM. This will kick off the driver/device - * binding...which will eventually call vmbus_match() and vmbus_probe() - */ - ret = device_register(&child_device_obj->device); - - if (ret) - pr_err("Unable to register child device\n"); - else - pr_info("child device %s registered\n", - dev_name(&child_device_obj->device)); - - return ret; -} - -/* - * vmbus_device_unregister - Remove the specified child device - * from the vmbus. - */ -void vmbus_device_unregister(struct hv_device *device_obj) -{ - /* - * Kick off the process of unregistering the device. - * This will call vmbus_remove() and eventually vmbus_device_release() - */ - device_unregister(&device_obj->device); - - pr_info("child device %s unregistered\n", - dev_name(&device_obj->device)); -} - - -/* - * VMBUS is an acpi enumerated device. Get the the IRQ information - * from DSDT. - */ - -static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq) -{ - - if (res->type == ACPI_RESOURCE_TYPE_IRQ) { - struct acpi_resource_irq *irqp; - irqp = &res->data.irq; - - *((unsigned int *)irq) = irqp->interrupts[0]; - } - - return AE_OK; -} - -static int vmbus_acpi_add(struct acpi_device *device) -{ - acpi_status result; - - hv_acpi_dev = device; - - result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - vmbus_walk_resources, &irq); - - if (ACPI_FAILURE(result)) { - complete(&probe_event); - return -ENODEV; - } - complete(&probe_event); - return 0; -} - -static const struct acpi_device_id vmbus_acpi_device_ids[] = { - {"VMBUS", 0}, - {"VMBus", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids); - -static struct acpi_driver vmbus_acpi_driver = { - .name = "vmbus", - .ids = vmbus_acpi_device_ids, - .ops = { - .add = vmbus_acpi_add, - }, -}; - -static int __init hv_acpi_init(void) -{ - int ret, t; - - init_completion(&probe_event); - - /* - * Get irq resources first. - */ - - ret = acpi_bus_register_driver(&vmbus_acpi_driver); - - if (ret) - return ret; - - t = wait_for_completion_timeout(&probe_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } - - if (irq <= 0) { - ret = -ENODEV; - goto cleanup; - } - - ret = vmbus_bus_init(irq); - if (ret) - goto cleanup; - - return 0; - -cleanup: - acpi_bus_unregister_driver(&vmbus_acpi_driver); - return ret; -} - - -MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); -module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR); - -module_init(hv_acpi_init); -- cgit v1.1 From d181daa06dd72fa88652b1d8bf723570a9fc55ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 11 Oct 2011 09:20:31 -0600 Subject: Staging: hv: storvsc: remove last usage of DPRINT_WARN Used the correct dev_warn() call instead. Cc: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index af185ab..1f9d23e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -510,20 +510,20 @@ static void storvsc_on_io_completion(struct hv_device *device, if (vstor_packet->vm_srb.scsi_status != 0 || vstor_packet->vm_srb.srb_status != 1){ - DPRINT_WARN(STORVSC, - "cmd 0x%x scsi status 0x%x srb status 0x%x\n", - stor_pkt->vm_srb.cdb[0], - vstor_packet->vm_srb.scsi_status, - vstor_packet->vm_srb.srb_status); + dev_warn(&device->device, + "cmd 0x%x scsi status 0x%x srb status 0x%x\n", + stor_pkt->vm_srb.cdb[0], + vstor_packet->vm_srb.scsi_status, + vstor_packet->vm_srb.srb_status); } if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { /* CHECK_CONDITION */ if (vstor_packet->vm_srb.srb_status & 0x80) { /* autosense data available */ - DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data " - "valid - len %d\n", request, - vstor_packet->vm_srb.sense_info_length); + dev_warn(&device->device, + "storvsc pkt %p autosense data valid - len %d\n", + request, vstor_packet->vm_srb.sense_info_length); memcpy(request->sense_buffer, vstor_packet->vm_srb.sense_data, -- cgit v1.1 From 1f46902371c50f72ef422e19119b8e3c0b0b3ef6 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 14 Oct 2011 21:31:56 -0700 Subject: Staging: hv: mousevsc: Fix a checkpatch warning Fix a checkpatch warning. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index c354ade..ccd39c7 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -597,4 +597,3 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); module_init(mousevsc_init); module_exit(mousevsc_exit); - -- cgit v1.1 From 41098f8f1473cf853125d2fde2ce936879ef1adc Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 14 Oct 2011 21:31:57 -0700 Subject: Staging: hv: storvsc: Fix checkpatch warnings Fix checkpatch warnings. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv') diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 1f9d23e..ae8c33e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -522,8 +522,9 @@ static void storvsc_on_io_completion(struct hv_device *device, if (vstor_packet->vm_srb.srb_status & 0x80) { /* autosense data available */ dev_warn(&device->device, - "storvsc pkt %p autosense data valid - len %d\n", - request, vstor_packet->vm_srb.sense_info_length); + "stor pkt %p autosense data valid - len %d\n", + request, + vstor_packet->vm_srb.sense_info_length); memcpy(request->sense_buffer, vstor_packet->vm_srb.sense_data, @@ -1128,13 +1129,13 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) u8 scsi_op = scmnd->cmnd[0]; switch (scsi_op) { - /* smartd sends this command, which will offline the device */ - case SET_WINDOW: - scmnd->result = DID_ERROR << 16; - allowed = false; - break; - default: - break; + /* smartd sends this command, which will offline the device */ + case SET_WINDOW: + scmnd->result = DID_ERROR << 16; + allowed = false; + break; + default: + break; } return allowed; } -- cgit v1.1