mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-27 20:48:11 +00:00
kernel: cherry-pick more VMBus patches, fix for yet another kernel crash
These are most of the changes to channel.c and channel_mgmt.c from upstream. They are needed to apply a proposed patch to fix yet another kernel crash we reported. This patch is also included. With these patches applied many thousand connections with random data and up to 10 concurrent connections are sustained without kernel crashes. This patch also updates the core Hyper-V socket support to v11 (which also obsoletes the previous patch added to work around a kernel bug) Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
parent
04d5a39638
commit
61b38236a9
@ -1,7 +1,7 @@
|
|||||||
From 31adb74f5668e7e44615a2854742f8726a818533 Mon Sep 17 00:00:00 2001
|
From 31adb74f5668e7e44615a2854742f8726a818533 Mon Sep 17 00:00:00 2001
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
Date: Thu, 17 Dec 2015 16:53:43 +0800
|
Date: Thu, 17 Dec 2015 16:53:43 +0800
|
||||||
Subject: [PATCH 01/28] virtio: make find_vqs() checkpatch.pl-friendly
|
Subject: [PATCH 01/40] virtio: make find_vqs() checkpatch.pl-friendly
|
||||||
|
|
||||||
checkpatch.pl wants arrays of strings declared as follows:
|
checkpatch.pl wants arrays of strings declared as follows:
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 4b274b13e7dfe4ac54072f324738c487a36b78b8 Mon Sep 17 00:00:00 2001
|
From 4b274b13e7dfe4ac54072f324738c487a36b78b8 Mon Sep 17 00:00:00 2001
|
||||||
From: Julia Lawall <julia.lawall@lip6.fr>
|
From: Julia Lawall <julia.lawall@lip6.fr>
|
||||||
Date: Sat, 21 Nov 2015 18:39:17 +0100
|
Date: Sat, 21 Nov 2015 18:39:17 +0100
|
||||||
Subject: [PATCH 02/28] VSOCK: constify vmci_transport_notify_ops structures
|
Subject: [PATCH 02/40] VSOCK: constify vmci_transport_notify_ops structures
|
||||||
|
|
||||||
The vmci_transport_notify_ops structures are never modified, so declare
|
The vmci_transport_notify_ops structures are never modified, so declare
|
||||||
them as const.
|
them as const.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 31fb7962193b46e8f7e24ac350e3efc486f0fd90 Mon Sep 17 00:00:00 2001
|
From 31fb7962193b46e8f7e24ac350e3efc486f0fd90 Mon Sep 17 00:00:00 2001
|
||||||
From: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
|
From: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
|
||||||
Date: Tue, 22 Mar 2016 17:05:52 +0100
|
Date: Tue, 22 Mar 2016 17:05:52 +0100
|
||||||
Subject: [PATCH 03/28] AF_VSOCK: Shrink the area influenced by prepare_to_wait
|
Subject: [PATCH 03/40] AF_VSOCK: Shrink the area influenced by prepare_to_wait
|
||||||
|
|
||||||
When a thread is prepared for waiting by calling prepare_to_wait, sleeping
|
When a thread is prepared for waiting by calling prepare_to_wait, sleeping
|
||||||
is not allowed until either the wait has taken place or finish_wait has
|
is not allowed until either the wait has taken place or finish_wait has
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 891b9c6111fc77750b261cc03f8ac7a80441701a Mon Sep 17 00:00:00 2001
|
From 891b9c6111fc77750b261cc03f8ac7a80441701a Mon Sep 17 00:00:00 2001
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
Date: Thu, 17 Dec 2015 11:10:21 +0800
|
Date: Thu, 17 Dec 2015 11:10:21 +0800
|
||||||
Subject: [PATCH 04/28] VSOCK: transport-specific vsock_transport functions
|
Subject: [PATCH 04/40] VSOCK: transport-specific vsock_transport functions
|
||||||
|
|
||||||
struct vsock_transport contains function pointers called by AF_VSOCK
|
struct vsock_transport contains function pointers called by AF_VSOCK
|
||||||
core code. The transport may want its own transport-specific function
|
core code. The transport may want its own transport-specific function
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From a27fee87d915bfb9edf720f9068c3aed6649aa0c Mon Sep 17 00:00:00 2001
|
From a27fee87d915bfb9edf720f9068c3aed6649aa0c Mon Sep 17 00:00:00 2001
|
||||||
From: Asias He <asias@redhat.com>
|
From: Asias He <asias@redhat.com>
|
||||||
Date: Thu, 13 Jun 2013 18:27:00 +0800
|
Date: Thu, 13 Jun 2013 18:27:00 +0800
|
||||||
Subject: [PATCH 05/28] VSOCK: Introduce virtio_vsock_common.ko
|
Subject: [PATCH 05/40] VSOCK: Introduce virtio_vsock_common.ko
|
||||||
|
|
||||||
This module contains the common code and header files for the following
|
This module contains the common code and header files for the following
|
||||||
virtio_transporto and vhost_vsock kernel modules.
|
virtio_transporto and vhost_vsock kernel modules.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 19cfdea4fa3fa9136c234ac695f628fce73b40c2 Mon Sep 17 00:00:00 2001
|
From 19cfdea4fa3fa9136c234ac695f628fce73b40c2 Mon Sep 17 00:00:00 2001
|
||||||
From: Asias He <asias@redhat.com>
|
From: Asias He <asias@redhat.com>
|
||||||
Date: Thu, 13 Jun 2013 18:28:48 +0800
|
Date: Thu, 13 Jun 2013 18:28:48 +0800
|
||||||
Subject: [PATCH 06/28] VSOCK: Introduce virtio_transport.ko
|
Subject: [PATCH 06/40] VSOCK: Introduce virtio_transport.ko
|
||||||
|
|
||||||
VM sockets virtio transport implementation. This driver runs in the
|
VM sockets virtio transport implementation. This driver runs in the
|
||||||
guest.
|
guest.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From fd467c3335938b8eca0489008c390ad16a01aee7 Mon Sep 17 00:00:00 2001
|
From fd467c3335938b8eca0489008c390ad16a01aee7 Mon Sep 17 00:00:00 2001
|
||||||
From: Asias He <asias@redhat.com>
|
From: Asias He <asias@redhat.com>
|
||||||
Date: Thu, 13 Jun 2013 18:29:21 +0800
|
Date: Thu, 13 Jun 2013 18:29:21 +0800
|
||||||
Subject: [PATCH 07/28] VSOCK: Introduce vhost_vsock.ko
|
Subject: [PATCH 07/40] VSOCK: Introduce vhost_vsock.ko
|
||||||
|
|
||||||
VM sockets vhost transport implementation. This driver runs on the
|
VM sockets vhost transport implementation. This driver runs on the
|
||||||
host.
|
host.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 5d2849bde15e969b8cf1eb2f5e818b62ec2181ec Mon Sep 17 00:00:00 2001
|
From 5d2849bde15e969b8cf1eb2f5e818b62ec2181ec Mon Sep 17 00:00:00 2001
|
||||||
From: Asias He <asias@redhat.com>
|
From: Asias He <asias@redhat.com>
|
||||||
Date: Thu, 13 Jun 2013 18:30:19 +0800
|
Date: Thu, 13 Jun 2013 18:30:19 +0800
|
||||||
Subject: [PATCH 08/28] VSOCK: Add Makefile and Kconfig
|
Subject: [PATCH 08/40] VSOCK: Add Makefile and Kconfig
|
||||||
|
|
||||||
Enable virtio-vsock and vhost-vsock.
|
Enable virtio-vsock and vhost-vsock.
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
From 81b78a051aa8c61743abcc266eb9c7511dd19a62 Mon Sep 17 00:00:00 2001
|
From 81b78a051aa8c61743abcc266eb9c7511dd19a62 Mon Sep 17 00:00:00 2001
|
||||||
From: Ian Campbell <ian.campbell@docker.com>
|
From: Ian Campbell <ian.campbell@docker.com>
|
||||||
Date: Mon, 4 Apr 2016 14:50:10 +0100
|
Date: Mon, 4 Apr 2016 14:50:10 +0100
|
||||||
Subject: [PATCH 09/28] VSOCK: Only allow host network namespace to use
|
Subject: [PATCH 09/40] VSOCK: Only allow host network namespace to use
|
||||||
AF_VSOCK.
|
AF_VSOCK.
|
||||||
|
|
||||||
The VSOCK addressing schema does not really lend itself to simply creating an
|
The VSOCK addressing schema does not really lend itself to simply creating an
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
From b5a27dd334aa0f8e857e751c81f79b1ed482459c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jake Oshins <jakeo@microsoft.com>
|
||||||
|
Date: Mon, 14 Dec 2015 16:01:41 -0800
|
||||||
|
Subject: [PATCH 10/40] drivers:hv: Define the channel type for Hyper-V PCI
|
||||||
|
Express pass-through
|
||||||
|
|
||||||
|
This defines the channel type for PCI front-ends in Hyper-V VMs.
|
||||||
|
|
||||||
|
Signed-off-by: Jake Oshins <jakeo@microsoft.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 3053c762444a83ec6a8777f9476668b23b8ab180)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 3 +++
|
||||||
|
include/linux/hyperv.h | 11 +++++++++++
|
||||||
|
2 files changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index 652afd1..a77646b 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -358,6 +358,7 @@ enum {
|
||||||
|
SCSI,
|
||||||
|
NIC,
|
||||||
|
ND_NIC,
|
||||||
|
+ PCIE,
|
||||||
|
MAX_PERF_CHN,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -375,6 +376,8 @@ static const struct hv_vmbus_device_id hp_devs[] = {
|
||||||
|
{ HV_NIC_GUID, },
|
||||||
|
/* NetworkDirect Guest RDMA */
|
||||||
|
{ HV_ND_GUID, },
|
||||||
|
+ /* PCI Express Pass Through */
|
||||||
|
+ { HV_PCIE_GUID, },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index ae6a711..10dda1e 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -1156,6 +1156,17 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * PCI Express Pass Through
|
||||||
|
+ * {44C4F61D-4444-4400-9D52-802E27EDE19F}
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#define HV_PCIE_GUID \
|
||||||
|
+ .guid = { \
|
||||||
|
+ 0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44, \
|
||||||
|
+ 0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Common header for Hyper-V ICs
|
||||||
|
*/
|
||||||
|
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,297 @@
|
|||||||
|
From 02c6472ed9ae7498a0510d76dd4840349f4c7e92 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||||
|
Date: Mon, 14 Dec 2015 16:01:43 -0800
|
||||||
|
Subject: [PATCH 11/40] Drivers: hv: vmbus: Use uuid_le type consistently
|
||||||
|
|
||||||
|
Consistently use uuid_le type in the Hyper-V driver code.
|
||||||
|
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit af3ff643ea91ba64dd8d0b1cbed54d44512f96cd)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 2 +-
|
||||||
|
drivers/hv/vmbus_drv.c | 10 ++---
|
||||||
|
include/linux/hyperv.h | 92 ++++++++++++++---------------------------
|
||||||
|
include/linux/mod_devicetable.h | 2 +-
|
||||||
|
scripts/mod/file2alias.c | 2 +-
|
||||||
|
5 files changed, 40 insertions(+), 68 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index a77646b..38470aa 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -408,7 +408,7 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
|
||||||
|
struct cpumask *alloced_mask;
|
||||||
|
|
||||||
|
for (i = IDE; i < MAX_PERF_CHN; i++) {
|
||||||
|
- if (!memcmp(type_guid->b, hp_devs[i].guid,
|
||||||
|
+ if (!memcmp(type_guid->b, &hp_devs[i].guid,
|
||||||
|
sizeof(uuid_le))) {
|
||||||
|
perf_chn = true;
|
||||||
|
break;
|
||||||
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
|
index f19b6f7..e64934e 100644
|
||||||
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
|
@@ -531,7 +531,7 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||||
|
|
||||||
|
static const uuid_le null_guid;
|
||||||
|
|
||||||
|
-static inline bool is_null_guid(const __u8 *guid)
|
||||||
|
+static inline bool is_null_guid(const uuid_le *guid)
|
||||||
|
{
|
||||||
|
if (memcmp(guid, &null_guid, sizeof(uuid_le)))
|
||||||
|
return false;
|
||||||
|
@@ -544,9 +544,9 @@ static inline bool is_null_guid(const __u8 *guid)
|
||||||
|
*/
|
||||||
|
static const struct hv_vmbus_device_id *hv_vmbus_get_id(
|
||||||
|
const struct hv_vmbus_device_id *id,
|
||||||
|
- const __u8 *guid)
|
||||||
|
+ const uuid_le *guid)
|
||||||
|
{
|
||||||
|
- for (; !is_null_guid(id->guid); id++)
|
||||||
|
+ for (; !is_null_guid(&id->guid); id++)
|
||||||
|
if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
@@ -563,7 +563,7 @@ 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))
|
||||||
|
+ if (hv_vmbus_get_id(drv->id_table, &hv_dev->dev_type))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -580,7 +580,7 @@ static int vmbus_probe(struct device *child_device)
|
||||||
|
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);
|
||||||
|
+ dev_id = hv_vmbus_get_id(drv->id_table, &dev->dev_type);
|
||||||
|
if (drv->probe) {
|
||||||
|
ret = drv->probe(dev, dev_id);
|
||||||
|
if (ret != 0)
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index 10dda1e..4712d7d 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -1012,6 +1012,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
.guid = { g0, g1, g2, g3, g4, g5, g6, g7, \
|
||||||
|
g8, g9, ga, gb, gc, gd, ge, gf },
|
||||||
|
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* GUID definitions of various offer types - services offered to the guest.
|
||||||
|
*/
|
||||||
|
@@ -1021,118 +1023,94 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
* {f8615163-df3e-46c5-913f-f2d2f965ed0e}
|
||||||
|
*/
|
||||||
|
#define HV_NIC_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46, \
|
||||||
|
- 0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0xf8615163, 0xdf3e, 0x46c5, 0x91, 0x3f, \
|
||||||
|
+ 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IDE GUID
|
||||||
|
* {32412632-86cb-44a2-9b5c-50d1417354f5}
|
||||||
|
*/
|
||||||
|
#define HV_IDE_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, \
|
||||||
|
- 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, \
|
||||||
|
+ 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCSI GUID
|
||||||
|
* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
|
||||||
|
*/
|
||||||
|
#define HV_SCSI_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, \
|
||||||
|
- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, \
|
||||||
|
+ 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shutdown GUID
|
||||||
|
* {0e0b6031-5213-4934-818b-38d90ced39db}
|
||||||
|
*/
|
||||||
|
#define HV_SHUTDOWN_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49, \
|
||||||
|
- 0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8b, \
|
||||||
|
+ 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time Synch GUID
|
||||||
|
* {9527E630-D0AE-497b-ADCE-E80AB0175CAF}
|
||||||
|
*/
|
||||||
|
#define HV_TS_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, \
|
||||||
|
- 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, \
|
||||||
|
+ 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Heartbeat GUID
|
||||||
|
* {57164f39-9115-4e78-ab55-382f3bd5422d}
|
||||||
|
*/
|
||||||
|
#define HV_HEART_BEAT_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, \
|
||||||
|
- 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, \
|
||||||
|
+ 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KVP GUID
|
||||||
|
* {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}
|
||||||
|
*/
|
||||||
|
#define HV_KVP_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, \
|
||||||
|
- 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, \
|
||||||
|
+ 0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic memory GUID
|
||||||
|
* {525074dc-8985-46e2-8057-a307dc18a502}
|
||||||
|
*/
|
||||||
|
#define HV_DM_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0xdc, 0x74, 0x50, 0X52, 0x85, 0x89, 0xe2, 0x46, \
|
||||||
|
- 0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x525074dc, 0x8985, 0x46e2, 0x80, 0x57, \
|
||||||
|
+ 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mouse GUID
|
||||||
|
* {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}
|
||||||
|
*/
|
||||||
|
#define HV_MOUSE_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x9e, 0xb6, 0xa8, 0xcf, 0x4a, 0x5b, 0xc0, 0x4c, \
|
||||||
|
- 0xb9, 0x8b, 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0xcfa8b69e, 0x5b4a, 0x4cc0, 0xb9, 0x8b, \
|
||||||
|
+ 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VSS (Backup/Restore) GUID
|
||||||
|
*/
|
||||||
|
#define HV_VSS_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42, \
|
||||||
|
- 0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x35fa2e29, 0xea23, 0x4236, 0x96, 0xae, \
|
||||||
|
+ 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40)
|
||||||
|
/*
|
||||||
|
* Synthetic Video GUID
|
||||||
|
* {DA0A7802-E377-4aac-8E77-0558EB1073F8}
|
||||||
|
*/
|
||||||
|
#define HV_SYNTHVID_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x02, 0x78, 0x0a, 0xda, 0x77, 0xe3, 0xac, 0x4a, \
|
||||||
|
- 0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0xda0a7802, 0xe377, 0x4aac, 0x8e, 0x77, \
|
||||||
|
+ 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Synthetic FC GUID
|
||||||
|
* {2f9bcc4a-0069-4af3-b76b-6fd0be528cda}
|
||||||
|
*/
|
||||||
|
#define HV_SYNTHFC_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x4A, 0xCC, 0x9B, 0x2F, 0x69, 0x00, 0xF3, 0x4A, \
|
||||||
|
- 0xB7, 0x6B, 0x6F, 0xD0, 0xBE, 0x52, 0x8C, 0xDA \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x2f9bcc4a, 0x0069, 0x4af3, 0xb7, 0x6b, \
|
||||||
|
+ 0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guest File Copy Service
|
||||||
|
@@ -1140,20 +1118,16 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HV_FCOPY_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0xE3, 0x4B, 0xD1, 0x34, 0xE4, 0xDE, 0xC8, 0x41, \
|
||||||
|
- 0x9A, 0xE7, 0x6B, 0x17, 0x49, 0x77, 0xC1, 0x92 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x34d14be3, 0xdee4, 0x41c8, 0x9a, 0xe7, \
|
||||||
|
+ 0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NetworkDirect. This is the guest RDMA service.
|
||||||
|
* {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}
|
||||||
|
*/
|
||||||
|
#define HV_ND_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x3d, 0xaf, 0x2e, 0x8c, 0xa7, 0x32, 0x09, 0x4b, \
|
||||||
|
- 0xab, 0x99, 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01 \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x8c2eaf3d, 0x32a7, 0x4b09, 0xab, 0x99, \
|
||||||
|
+ 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCI Express Pass Through
|
||||||
|
@@ -1161,10 +1135,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HV_PCIE_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44, \
|
||||||
|
- 0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F \
|
||||||
|
- }
|
||||||
|
+ .guid = UUID_LE(0x44c4f61d, 0x4444, 0x4400, 0x9d, 0x52, \
|
||||||
|
+ 0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common header for Hyper-V ICs
|
||||||
|
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
|
||||||
|
index 64f36e0..6e4c645 100644
|
||||||
|
--- a/include/linux/mod_devicetable.h
|
||||||
|
+++ b/include/linux/mod_devicetable.h
|
||||||
|
@@ -404,7 +404,7 @@ struct virtio_device_id {
|
||||||
|
* For Hyper-V devices we use the device guid as the id.
|
||||||
|
*/
|
||||||
|
struct hv_vmbus_device_id {
|
||||||
|
- __u8 guid[16];
|
||||||
|
+ uuid_le guid;
|
||||||
|
kernel_ulong_t driver_data; /* Data private to the driver */
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
|
||||||
|
index 5b96206..8adca44 100644
|
||||||
|
--- a/scripts/mod/file2alias.c
|
||||||
|
+++ b/scripts/mod/file2alias.c
|
||||||
|
@@ -917,7 +917,7 @@ static int do_vmbus_entry(const char *filename, void *symval,
|
||||||
|
char guid_name[(sizeof(*guid) + 1) * 2];
|
||||||
|
|
||||||
|
for (i = 0; i < (sizeof(*guid) * 2); i += 2)
|
||||||
|
- sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2]));
|
||||||
|
+ sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
|
||||||
|
|
||||||
|
strcpy(alias, "vmbus:");
|
||||||
|
strcat(alias, guid_name);
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
From d8a7b4073f802509ad00164b1d6967ba9ebb9d7f Mon Sep 17 00:00:00 2001
|
||||||
|
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||||
|
Date: Mon, 14 Dec 2015 16:01:44 -0800
|
||||||
|
Subject: [PATCH 12/40] Drivers: hv: vmbus: Use uuid_le_cmp() for comparing
|
||||||
|
GUIDs
|
||||||
|
|
||||||
|
Use uuid_le_cmp() for comparing GUIDs.
|
||||||
|
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 4ae9250893485f380275e7d5cb291df87c4d9710)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 3 +--
|
||||||
|
drivers/hv/vmbus_drv.c | 4 ++--
|
||||||
|
2 files changed, 3 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index 38470aa..dc4fb0b 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -408,8 +408,7 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
|
||||||
|
struct cpumask *alloced_mask;
|
||||||
|
|
||||||
|
for (i = IDE; i < MAX_PERF_CHN; i++) {
|
||||||
|
- if (!memcmp(type_guid->b, &hp_devs[i].guid,
|
||||||
|
- sizeof(uuid_le))) {
|
||||||
|
+ if (!uuid_le_cmp(*type_guid, hp_devs[i].guid)) {
|
||||||
|
perf_chn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
|
index e64934e..aa4d8cc 100644
|
||||||
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
|
@@ -533,7 +533,7 @@ static const uuid_le null_guid;
|
||||||
|
|
||||||
|
static inline bool is_null_guid(const uuid_le *guid)
|
||||||
|
{
|
||||||
|
- if (memcmp(guid, &null_guid, sizeof(uuid_le)))
|
||||||
|
+ if (uuid_le_cmp(*guid, null_guid))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@@ -547,7 +547,7 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(
|
||||||
|
const uuid_le *guid)
|
||||||
|
{
|
||||||
|
for (; !is_null_guid(&id->guid); id++)
|
||||||
|
- if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
|
||||||
|
+ if (!uuid_le_cmp(id->guid, *guid))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From c4795172e48b3229b24b3816c4c0d822c2cd2b88 Mon Sep 17 00:00:00 2001
|
From e24d6e93c8ee5110240547663c88b909fbed3575 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 14 Dec 2015 16:01:47 -0800
|
Date: Mon, 14 Dec 2015 16:01:47 -0800
|
||||||
Subject: [PATCH 10/28] Drivers: hv: vmbus: serialize process_chn_event() and
|
Subject: [PATCH 13/40] Drivers: hv: vmbus: serialize process_chn_event() and
|
||||||
vmbus_close_internal()
|
vmbus_close_internal()
|
||||||
|
|
||||||
process_chn_event(), running in the tasklet, can race with
|
process_chn_event(), running in the tasklet, can race with
|
@ -1,7 +1,7 @@
|
|||||||
From db7c4decfd08e194c3fe7647ebc0903c5fee33b7 Mon Sep 17 00:00:00 2001
|
From d744926ed8c8f1b717d7ab04adf0d86aa78b1160 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 14 Dec 2015 16:01:48 -0800
|
Date: Mon, 14 Dec 2015 16:01:48 -0800
|
||||||
Subject: [PATCH 11/28] Drivers: hv: vmbus: do sanity check of channel state in
|
Subject: [PATCH 14/40] Drivers: hv: vmbus: do sanity check of channel state in
|
||||||
vmbus_close_internal()
|
vmbus_close_internal()
|
||||||
|
|
||||||
This fixes an incorrect assumption of channel state in the function.
|
This fixes an incorrect assumption of channel state in the function.
|
@ -1,7 +1,7 @@
|
|||||||
From 92aa99cab10f5beb241635eee20fd1709fb63196 Mon Sep 17 00:00:00 2001
|
From ae5614842c1b80193552aeabb57f6cc37c5ca848 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 14 Dec 2015 16:01:49 -0800
|
Date: Mon, 14 Dec 2015 16:01:49 -0800
|
||||||
Subject: [PATCH 12/28] Drivers: hv: vmbus: fix rescind-offer handling for
|
Subject: [PATCH 15/40] Drivers: hv: vmbus: fix rescind-offer handling for
|
||||||
device without a driver
|
device without a driver
|
||||||
|
|
||||||
In the path vmbus_onoffer_rescind() -> vmbus_device_unregister() ->
|
In the path vmbus_onoffer_rescind() -> vmbus_device_unregister() ->
|
||||||
@ -55,7 +55,7 @@ index b3c14ca..2889d97 100644
|
|||||||
tasklet_enable(tasklet);
|
tasklet_enable(tasklet);
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index 652afd1..bd2e9f6 100644
|
index dc4fb0b..7903acc 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -191,6 +191,8 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
@@ -191,6 +191,8 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||||
@ -79,7 +79,7 @@ index 652afd1..bd2e9f6 100644
|
|||||||
|
|
||||||
vmbus_device_unregister(channel->device_obj);
|
vmbus_device_unregister(channel->device_obj);
|
||||||
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
index f19b6f7..7e46a48 100644
|
index aa4d8cc..5a71b2a 100644
|
||||||
--- a/drivers/hv/vmbus_drv.c
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
+++ b/drivers/hv/vmbus_drv.c
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
@@ -602,23 +602,11 @@ static int vmbus_remove(struct device *child_device)
|
@@ -602,23 +602,11 @@ static int vmbus_remove(struct device *child_device)
|
@ -1,7 +1,7 @@
|
|||||||
From c0e232b85b7cf4387788962085fed314e01b5e8c Mon Sep 17 00:00:00 2001
|
From 28d0ed01c7b183c6af5991351de65046c183f392 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 14 Dec 2015 16:01:50 -0800
|
Date: Mon, 14 Dec 2015 16:01:50 -0800
|
||||||
Subject: [PATCH 13/28] Drivers: hv: vmbus: release relid on error in
|
Subject: [PATCH 16/40] Drivers: hv: vmbus: release relid on error in
|
||||||
vmbus_process_offer()
|
vmbus_process_offer()
|
||||||
|
|
||||||
We want to simplify vmbus_onoffer_rescind() by not invoking
|
We want to simplify vmbus_onoffer_rescind() by not invoking
|
||||||
@ -16,7 +16,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
1 file changed, 15 insertions(+), 6 deletions(-)
|
1 file changed, 15 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index bd2e9f6..df76a71 100644
|
index 7903acc..9c9da3a 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -177,19 +177,22 @@ static void percpu_channel_deq(void *arg)
|
@@ -177,19 +177,22 @@ static void percpu_channel_deq(void *arg)
|
||||||
@ -56,7 +56,7 @@ index bd2e9f6..df76a71 100644
|
|||||||
spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
|
spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
|
||||||
list_del(&newchannel->listentry);
|
list_del(&newchannel->listentry);
|
||||||
spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
|
spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
|
||||||
@@ -585,7 +590,11 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -587,7 +592,11 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
channel = relid2channel(rescind->child_relid);
|
channel = relid2channel(rescind->child_relid);
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
@ -1,7 +1,7 @@
|
|||||||
From 2991041546570f369440c4837ae5ef0518e4d839 Mon Sep 17 00:00:00 2001
|
From 9aa8a05fcf39739b23f8e2f502c3ffa370521cba Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 14 Dec 2015 16:01:51 -0800
|
Date: Mon, 14 Dec 2015 16:01:51 -0800
|
||||||
Subject: [PATCH 14/28] Drivers: hv: vmbus: channge
|
Subject: [PATCH 17/40] Drivers: hv: vmbus: channge
|
||||||
vmbus_connection.channel_lock to mutex
|
vmbus_connection.channel_lock to mutex
|
||||||
|
|
||||||
spinlock is unnecessary here.
|
spinlock is unnecessary here.
|
||||||
@ -18,7 +18,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
3 files changed, 10 insertions(+), 11 deletions(-)
|
3 files changed, 10 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index df76a71..bd4f084 100644
|
index 9c9da3a..d013171 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -206,9 +206,9 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
@@ -206,9 +206,9 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
@ -0,0 +1,126 @@
|
|||||||
|
From 86e233fbb4c41b03096f498b26cdbfbdf9e5723e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Date: Mon, 14 Dec 2015 19:02:00 -0800
|
||||||
|
Subject: [PATCH 18/40] Drivers: hv: remove code duplication between
|
||||||
|
vmbus_recvpacket()/vmbus_recvpacket_raw()
|
||||||
|
|
||||||
|
vmbus_recvpacket() and vmbus_recvpacket_raw() are almost identical but
|
||||||
|
there are two discrepancies:
|
||||||
|
1) vmbus_recvpacket() doesn't propagate errors from hv_ringbuffer_read()
|
||||||
|
which looks like it is not desired.
|
||||||
|
2) There is an error message printed in packetlen > bufferlen case in
|
||||||
|
vmbus_recvpacket(). I'm removing it as it is usless for users to see
|
||||||
|
such messages and /vmbus_recvpacket_raw() doesn't have it.
|
||||||
|
|
||||||
|
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 667d374064b0cc48b6122101b287908d1b392bdb)
|
||||||
|
---
|
||||||
|
drivers/hv/channel.c | 65 ++++++++++++++++++----------------------------------
|
||||||
|
1 file changed, 22 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||||
|
index 2889d97..dd6de7f 100644
|
||||||
|
--- a/drivers/hv/channel.c
|
||||||
|
+++ b/drivers/hv/channel.c
|
||||||
|
@@ -922,8 +922,10 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
|
||||||
|
*
|
||||||
|
* Mainly used by Hyper-V drivers.
|
||||||
|
*/
|
||||||
|
-int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||||
|
- u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
|
||||||
|
+static inline int
|
||||||
|
+__vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||||
|
+ u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
|
||||||
|
+ bool raw)
|
||||||
|
{
|
||||||
|
struct vmpacket_descriptor desc;
|
||||||
|
u32 packetlen;
|
||||||
|
@@ -941,27 +943,34 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
packetlen = desc.len8 << 3;
|
||||||
|
- userlen = packetlen - (desc.offset8 << 3);
|
||||||
|
+ if (!raw)
|
||||||
|
+ userlen = packetlen - (desc.offset8 << 3);
|
||||||
|
+ else
|
||||||
|
+ userlen = packetlen;
|
||||||
|
|
||||||
|
*buffer_actual_len = userlen;
|
||||||
|
|
||||||
|
- if (userlen > bufferlen) {
|
||||||
|
-
|
||||||
|
- pr_err("Buffer too small - got %d needs %d\n",
|
||||||
|
- bufferlen, userlen);
|
||||||
|
- return -ETOOSMALL;
|
||||||
|
- }
|
||||||
|
+ if (userlen > bufferlen)
|
||||||
|
+ return -ENOBUFS;
|
||||||
|
|
||||||
|
*requestid = desc.trans_id;
|
||||||
|
|
||||||
|
/* Copy over the packet to the user buffer */
|
||||||
|
ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
|
||||||
|
- (desc.offset8 << 3), &signal);
|
||||||
|
+ raw ? 0 : desc.offset8 << 3, &signal);
|
||||||
|
|
||||||
|
if (signal)
|
||||||
|
vmbus_setevent(channel);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||||
|
+ u32 bufferlen, u32 *buffer_actual_len,
|
||||||
|
+ u64 *requestid)
|
||||||
|
+{
|
||||||
|
+ return __vmbus_recvpacket(channel, buffer, bufferlen,
|
||||||
|
+ buffer_actual_len, requestid, false);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(vmbus_recvpacket);
|
||||||
|
|
||||||
|
@@ -972,37 +981,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
|
||||||
|
u32 bufferlen, u32 *buffer_actual_len,
|
||||||
|
u64 *requestid)
|
||||||
|
{
|
||||||
|
- struct vmpacket_descriptor desc;
|
||||||
|
- u32 packetlen;
|
||||||
|
- int ret;
|
||||||
|
- bool signal = false;
|
||||||
|
-
|
||||||
|
- *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;
|
||||||
|
-
|
||||||
|
- *buffer_actual_len = packetlen;
|
||||||
|
-
|
||||||
|
- if (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,
|
||||||
|
- &signal);
|
||||||
|
-
|
||||||
|
- if (signal)
|
||||||
|
- vmbus_setevent(channel);
|
||||||
|
-
|
||||||
|
- return ret;
|
||||||
|
+ return __vmbus_recvpacket(channel, buffer, bufferlen,
|
||||||
|
+ buffer_actual_len, requestid, true);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,72 @@
|
|||||||
|
From 934477d473ecb1facd9f69cfc4b4591598f3b0ed Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
|
Date: Mon, 21 Dec 2015 12:21:22 -0800
|
||||||
|
Subject: [PATCH 19/40] Drivers: hv: vmbus: fix the building warning with
|
||||||
|
hyperv-keyboard
|
||||||
|
|
||||||
|
With the recent change af3ff643ea91ba64dd8d0b1cbed54d44512f96cd
|
||||||
|
(Drivers: hv: vmbus: Use uuid_le type consistently), we always get this
|
||||||
|
warning:
|
||||||
|
|
||||||
|
CC [M] drivers/input/serio/hyperv-keyboard.o
|
||||||
|
drivers/input/serio/hyperv-keyboard.c:427:2: warning: missing braces around
|
||||||
|
initializer [-Wmissing-braces]
|
||||||
|
{ HV_KBD_GUID, },
|
||||||
|
^
|
||||||
|
drivers/input/serio/hyperv-keyboard.c:427:2: warning: (near initialization
|
||||||
|
for .id_table[0].guid.b.) [-Wmissing-braces]
|
||||||
|
|
||||||
|
The patch fixes the warning.
|
||||||
|
|
||||||
|
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 2048157ad02e65f6327118dd4a7b9c9f1fd12f77)
|
||||||
|
---
|
||||||
|
drivers/input/serio/hyperv-keyboard.c | 10 ----------
|
||||||
|
include/linux/hyperv.h | 8 ++++++++
|
||||||
|
2 files changed, 8 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
|
||||||
|
index e74e5d6..c948866 100644
|
||||||
|
--- a/drivers/input/serio/hyperv-keyboard.c
|
||||||
|
+++ b/drivers/input/serio/hyperv-keyboard.c
|
||||||
|
@@ -412,16 +412,6 @@ static int hv_kbd_remove(struct hv_device *hv_dev)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Keyboard GUID
|
||||||
|
- * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
|
||||||
|
- */
|
||||||
|
-#define HV_KBD_GUID \
|
||||||
|
- .guid = { \
|
||||||
|
- 0x6d, 0xad, 0x12, 0xf9, 0x17, 0x2b, 0xea, 0x48, \
|
||||||
|
- 0xbd, 0x65, 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84 \
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
static const struct hv_vmbus_device_id id_table[] = {
|
||||||
|
/* Keyboard guid */
|
||||||
|
{ HV_KBD_GUID, },
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index 4712d7d..9e2de6a 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -1091,6 +1091,14 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||||
|
0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a)
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Keyboard GUID
|
||||||
|
+ * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
|
||||||
|
+ */
|
||||||
|
+#define HV_KBD_GUID \
|
||||||
|
+ .guid = UUID_LE(0xf912ad6d, 0x2b17, 0x48ea, 0xbd, 0x65, \
|
||||||
|
+ 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* VSS (Backup/Restore) GUID
|
||||||
|
*/
|
||||||
|
#define HV_VSS_GUID \
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From e952f2c22a0a2dbf6b56f732ce265aa6c9f461b2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||||
|
Date: Tue, 15 Dec 2015 16:27:27 -0800
|
||||||
|
Subject: [PATCH 20/40] Drivers: hv: vmbus: Treat Fibre Channel devices as
|
||||||
|
performance critical
|
||||||
|
|
||||||
|
For performance critical devices, we distribute the incoming
|
||||||
|
channel interrupt load across available CPUs in the guest.
|
||||||
|
Include Fibre channel devices in the set of devices for which
|
||||||
|
we would distribute the interrupt load.
|
||||||
|
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 879a650a273bc3efb9d472886b8ced12630ea8ed)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index d013171..1c1ad47 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -361,6 +361,7 @@ err_free_chan:
|
||||||
|
enum {
|
||||||
|
IDE = 0,
|
||||||
|
SCSI,
|
||||||
|
+ FC,
|
||||||
|
NIC,
|
||||||
|
ND_NIC,
|
||||||
|
PCIE,
|
||||||
|
@@ -377,6 +378,8 @@ static const struct hv_vmbus_device_id hp_devs[] = {
|
||||||
|
{ HV_IDE_GUID, },
|
||||||
|
/* Storage - SCSI */
|
||||||
|
{ HV_SCSI_GUID, },
|
||||||
|
+ /* Storage - FC */
|
||||||
|
+ { HV_SYNTHFC_GUID, },
|
||||||
|
/* Network */
|
||||||
|
{ HV_NIC_GUID, },
|
||||||
|
/* NetworkDirect Guest RDMA */
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,355 @@
|
|||||||
|
From cd2ba91482cea0e0979336c7e174224c39ab4537 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||||
|
Date: Fri, 25 Dec 2015 20:00:30 -0800
|
||||||
|
Subject: [PATCH 21/40] Drivers: hv: vmbus: Add vendor and device atttributes
|
||||||
|
|
||||||
|
Add vendor and device attributes to VMBUS devices. These will be used
|
||||||
|
by Hyper-V tools as well user-level RDMA libraries that will use the
|
||||||
|
vendor/device tuple to discover the RDMA device.
|
||||||
|
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 7047f17d70fc0599563d30d0791692cb5fe42ae6)
|
||||||
|
---
|
||||||
|
Documentation/ABI/stable/sysfs-bus-vmbus | 14 +++
|
||||||
|
drivers/hv/channel_mgmt.c | 166 +++++++++++++++++++++++--------
|
||||||
|
drivers/hv/vmbus_drv.c | 21 ++++
|
||||||
|
include/linux/hyperv.h | 28 ++++++
|
||||||
|
4 files changed, 186 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus
|
||||||
|
index 636e938..5d0125f 100644
|
||||||
|
--- a/Documentation/ABI/stable/sysfs-bus-vmbus
|
||||||
|
+++ b/Documentation/ABI/stable/sysfs-bus-vmbus
|
||||||
|
@@ -27,3 +27,17 @@ Description: The mapping of which primary/sub channels are bound to which
|
||||||
|
Virtual Processors.
|
||||||
|
Format: <channel's child_relid:the bound cpu's number>
|
||||||
|
Users: tools/hv/lsvmbus
|
||||||
|
+
|
||||||
|
+What: /sys/bus/vmbus/devices/vmbus_*/device
|
||||||
|
+Date: Dec. 2015
|
||||||
|
+KernelVersion: 4.5
|
||||||
|
+Contact: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
+Description: The 16 bit device ID of the device
|
||||||
|
+Users: tools/hv/lsvmbus and user level RDMA libraries
|
||||||
|
+
|
||||||
|
+What: /sys/bus/vmbus/devices/vmbus_*/vendor
|
||||||
|
+Date: Dec. 2015
|
||||||
|
+KernelVersion: 4.5
|
||||||
|
+Contact: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
+Description: The 16 bit vendor ID of the device
|
||||||
|
+Users: tools/hv/lsvmbus and user level RDMA libraries
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index 1c1ad47..107d72f 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -32,8 +32,122 @@
|
||||||
|
|
||||||
|
#include "hyperv_vmbus.h"
|
||||||
|
|
||||||
|
-static void init_vp_index(struct vmbus_channel *channel,
|
||||||
|
- const uuid_le *type_guid);
|
||||||
|
+static void init_vp_index(struct vmbus_channel *channel, u16 dev_type);
|
||||||
|
+
|
||||||
|
+static const struct vmbus_device vmbus_devs[] = {
|
||||||
|
+ /* IDE */
|
||||||
|
+ { .dev_type = HV_IDE,
|
||||||
|
+ HV_IDE_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* SCSI */
|
||||||
|
+ { .dev_type = HV_SCSI,
|
||||||
|
+ HV_SCSI_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Fibre Channel */
|
||||||
|
+ { .dev_type = HV_FC,
|
||||||
|
+ HV_SYNTHFC_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Synthetic NIC */
|
||||||
|
+ { .dev_type = HV_NIC,
|
||||||
|
+ HV_NIC_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Network Direct */
|
||||||
|
+ { .dev_type = HV_ND,
|
||||||
|
+ HV_ND_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* PCIE */
|
||||||
|
+ { .dev_type = HV_PCIE,
|
||||||
|
+ HV_PCIE_GUID,
|
||||||
|
+ .perf_device = true,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Synthetic Frame Buffer */
|
||||||
|
+ { .dev_type = HV_FB,
|
||||||
|
+ HV_SYNTHVID_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Synthetic Keyboard */
|
||||||
|
+ { .dev_type = HV_KBD,
|
||||||
|
+ HV_KBD_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Synthetic MOUSE */
|
||||||
|
+ { .dev_type = HV_MOUSE,
|
||||||
|
+ HV_MOUSE_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* KVP */
|
||||||
|
+ { .dev_type = HV_KVP,
|
||||||
|
+ HV_KVP_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Time Synch */
|
||||||
|
+ { .dev_type = HV_TS,
|
||||||
|
+ HV_TS_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Heartbeat */
|
||||||
|
+ { .dev_type = HV_HB,
|
||||||
|
+ HV_HEART_BEAT_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Shutdown */
|
||||||
|
+ { .dev_type = HV_SHUTDOWN,
|
||||||
|
+ HV_SHUTDOWN_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* File copy */
|
||||||
|
+ { .dev_type = HV_FCOPY,
|
||||||
|
+ HV_FCOPY_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Backup */
|
||||||
|
+ { .dev_type = HV_BACKUP,
|
||||||
|
+ HV_VSS_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Dynamic Memory */
|
||||||
|
+ { .dev_type = HV_DM,
|
||||||
|
+ HV_DM_GUID,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ /* Unknown GUID */
|
||||||
|
+ { .dev_type = HV_UNKOWN,
|
||||||
|
+ .perf_device = false,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static u16 hv_get_dev_type(const uuid_le *guid)
|
||||||
|
+{
|
||||||
|
+ u16 i;
|
||||||
|
+
|
||||||
|
+ for (i = HV_IDE; i < HV_UNKOWN; i++) {
|
||||||
|
+ if (!uuid_le_cmp(*guid, vmbus_devs[i].guid))
|
||||||
|
+ return i;
|
||||||
|
+ }
|
||||||
|
+ pr_info("Unknown GUID: %pUl\n", guid);
|
||||||
|
+ return i;
|
||||||
|
+}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
|
||||||
|
@@ -251,6 +365,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
struct vmbus_channel *channel;
|
||||||
|
bool fnew = true;
|
||||||
|
unsigned long flags;
|
||||||
|
+ u16 dev_type;
|
||||||
|
|
||||||
|
/* Make sure this is a new offer */
|
||||||
|
mutex_lock(&vmbus_connection.channel_mutex);
|
||||||
|
@@ -288,7 +403,9 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
goto err_free_chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
- init_vp_index(newchannel, &newchannel->offermsg.offer.if_type);
|
||||||
|
+ dev_type = hv_get_dev_type(&newchannel->offermsg.offer.if_type);
|
||||||
|
+
|
||||||
|
+ init_vp_index(newchannel, dev_type);
|
||||||
|
|
||||||
|
if (newchannel->target_cpu != get_cpu()) {
|
||||||
|
put_cpu();
|
||||||
|
@@ -325,6 +442,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
if (!newchannel->device_obj)
|
||||||
|
goto err_deq_chan;
|
||||||
|
|
||||||
|
+ newchannel->device_obj->device_id = dev_type;
|
||||||
|
/*
|
||||||
|
* Add the new device to the bus. This will kick off device-driver
|
||||||
|
* binding which eventually invokes the device driver's AddDevice()
|
||||||
|
@@ -358,37 +476,6 @@ err_free_chan:
|
||||||
|
free_channel(newchannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
-enum {
|
||||||
|
- IDE = 0,
|
||||||
|
- SCSI,
|
||||||
|
- FC,
|
||||||
|
- NIC,
|
||||||
|
- ND_NIC,
|
||||||
|
- PCIE,
|
||||||
|
- MAX_PERF_CHN,
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
- * This is an array of device_ids (device types) that are performance critical.
|
||||||
|
- * We attempt to distribute the interrupt load for these devices across
|
||||||
|
- * all available CPUs.
|
||||||
|
- */
|
||||||
|
-static const struct hv_vmbus_device_id hp_devs[] = {
|
||||||
|
- /* IDE */
|
||||||
|
- { HV_IDE_GUID, },
|
||||||
|
- /* Storage - SCSI */
|
||||||
|
- { HV_SCSI_GUID, },
|
||||||
|
- /* Storage - FC */
|
||||||
|
- { HV_SYNTHFC_GUID, },
|
||||||
|
- /* Network */
|
||||||
|
- { HV_NIC_GUID, },
|
||||||
|
- /* NetworkDirect Guest RDMA */
|
||||||
|
- { HV_ND_GUID, },
|
||||||
|
- /* PCI Express Pass Through */
|
||||||
|
- { HV_PCIE_GUID, },
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* We use this state to statically distribute the channel interrupt load.
|
||||||
|
*/
|
||||||
|
@@ -405,22 +492,15 @@ static int next_numa_node_id;
|
||||||
|
* For pre-win8 hosts or non-performance critical channels we assign the
|
||||||
|
* first CPU in the first NUMA node.
|
||||||
|
*/
|
||||||
|
-static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_guid)
|
||||||
|
+static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
|
||||||
|
{
|
||||||
|
u32 cur_cpu;
|
||||||
|
- int i;
|
||||||
|
- bool perf_chn = false;
|
||||||
|
+ bool perf_chn = vmbus_devs[dev_type].perf_device;
|
||||||
|
struct vmbus_channel *primary = channel->primary_channel;
|
||||||
|
int next_node;
|
||||||
|
struct cpumask available_mask;
|
||||||
|
struct cpumask *alloced_mask;
|
||||||
|
|
||||||
|
- for (i = IDE; i < MAX_PERF_CHN; i++) {
|
||||||
|
- if (!uuid_le_cmp(*type_guid, hp_devs[i].guid)) {
|
||||||
|
- perf_chn = true;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
if ((vmbus_proto_version == VERSION_WS2008) ||
|
||||||
|
(vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
|
||||||
|
/*
|
||||||
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
|
index 5a71b2a..3b83dfe 100644
|
||||||
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
|
@@ -478,6 +478,24 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RO(channel_vp_mapping);
|
||||||
|
|
||||||
|
+static ssize_t vendor_show(struct device *dev,
|
||||||
|
+ struct device_attribute *dev_attr,
|
||||||
|
+ char *buf)
|
||||||
|
+{
|
||||||
|
+ struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
|
+ return sprintf(buf, "0x%x\n", hv_dev->vendor_id);
|
||||||
|
+}
|
||||||
|
+static DEVICE_ATTR_RO(vendor);
|
||||||
|
+
|
||||||
|
+static ssize_t device_show(struct device *dev,
|
||||||
|
+ struct device_attribute *dev_attr,
|
||||||
|
+ char *buf)
|
||||||
|
+{
|
||||||
|
+ struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
|
+ return sprintf(buf, "0x%x\n", hv_dev->device_id);
|
||||||
|
+}
|
||||||
|
+static DEVICE_ATTR_RO(device);
|
||||||
|
+
|
||||||
|
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
|
||||||
|
static struct attribute *vmbus_attrs[] = {
|
||||||
|
&dev_attr_id.attr,
|
||||||
|
@@ -503,6 +521,8 @@ static struct attribute *vmbus_attrs[] = {
|
||||||
|
&dev_attr_in_read_bytes_avail.attr,
|
||||||
|
&dev_attr_in_write_bytes_avail.attr,
|
||||||
|
&dev_attr_channel_vp_mapping.attr,
|
||||||
|
+ &dev_attr_vendor.attr,
|
||||||
|
+ &dev_attr_device.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
ATTRIBUTE_GROUPS(vmbus);
|
||||||
|
@@ -957,6 +977,7 @@ struct hv_device *vmbus_device_create(const uuid_le *type,
|
||||||
|
memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
|
||||||
|
memcpy(&child_device_obj->dev_instance, instance,
|
||||||
|
sizeof(uuid_le));
|
||||||
|
+ child_device_obj->vendor_id = 0x1414; /* MSFT vendor ID */
|
||||||
|
|
||||||
|
|
||||||
|
return child_device_obj;
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index 9e2de6a..51c98fd 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -635,6 +635,32 @@ enum hv_signal_policy {
|
||||||
|
HV_SIGNAL_POLICY_EXPLICIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
+enum vmbus_device_type {
|
||||||
|
+ HV_IDE = 0,
|
||||||
|
+ HV_SCSI,
|
||||||
|
+ HV_FC,
|
||||||
|
+ HV_NIC,
|
||||||
|
+ HV_ND,
|
||||||
|
+ HV_PCIE,
|
||||||
|
+ HV_FB,
|
||||||
|
+ HV_KBD,
|
||||||
|
+ HV_MOUSE,
|
||||||
|
+ HV_KVP,
|
||||||
|
+ HV_TS,
|
||||||
|
+ HV_HB,
|
||||||
|
+ HV_SHUTDOWN,
|
||||||
|
+ HV_FCOPY,
|
||||||
|
+ HV_BACKUP,
|
||||||
|
+ HV_DM,
|
||||||
|
+ HV_UNKOWN,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct vmbus_device {
|
||||||
|
+ u16 dev_type;
|
||||||
|
+ uuid_le guid;
|
||||||
|
+ bool perf_device;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct vmbus_channel {
|
||||||
|
/* Unique channel id */
|
||||||
|
int id;
|
||||||
|
@@ -961,6 +987,8 @@ struct hv_device {
|
||||||
|
|
||||||
|
/* the device instance id of this device */
|
||||||
|
uuid_le dev_instance;
|
||||||
|
+ u16 vendor_id;
|
||||||
|
+ u16 device_id;
|
||||||
|
|
||||||
|
struct device device;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 38a40857bb22894545830b22fb593241f2fabf4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Date: Wed, 27 Jan 2016 22:29:34 -0800
|
||||||
|
Subject: [PATCH 22/40] Drivers: hv: vmbus: avoid infinite loop in
|
||||||
|
init_vp_index()
|
||||||
|
|
||||||
|
When we pick a CPU to use for a new subchannel we try find a non-used one
|
||||||
|
on the appropriate NUMA node, we keep track of them with the
|
||||||
|
primary->alloced_cpus_in_node mask. Under normal circumstances we don't run
|
||||||
|
out of available CPUs but it is possible when we we don't initialize some
|
||||||
|
cpus in Linux, e.g. when we boot with 'nr_cpus=' limitation.
|
||||||
|
|
||||||
|
Avoid the infinite loop in init_vp_index() by checking that we still have
|
||||||
|
non-used CPUs in the alloced_cpus_in_node mask and resetting it in case
|
||||||
|
we don't.
|
||||||
|
|
||||||
|
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 79fd8e706637a5c7c41f9498fe0fbfb437abfdc8)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index 107d72f..af1d82e 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -549,6 +549,17 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
|
||||||
|
cpumask_of_node(primary->numa_node));
|
||||||
|
|
||||||
|
cur_cpu = -1;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Normally Hyper-V host doesn't create more subchannels than there
|
||||||
|
+ * are VCPUs on the node but it is possible when not all present VCPUs
|
||||||
|
+ * on the node are initialized by guest. Clear the alloced_cpus_in_node
|
||||||
|
+ * to start over.
|
||||||
|
+ */
|
||||||
|
+ if (cpumask_equal(&primary->alloced_cpus_in_node,
|
||||||
|
+ cpumask_of_node(primary->numa_node)))
|
||||||
|
+ cpumask_clear(&primary->alloced_cpus_in_node);
|
||||||
|
+
|
||||||
|
while (true) {
|
||||||
|
cur_cpu = cpumask_next(cur_cpu, &available_mask);
|
||||||
|
if (cur_cpu >= nr_cpu_ids) {
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
From 22945cbc393c06b0b55c553623b595fc1e6d2598 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Date: Wed, 27 Jan 2016 22:29:35 -0800
|
||||||
|
Subject: [PATCH 23/40] Drivers: hv: vmbus: avoid scheduling in interrupt
|
||||||
|
context in vmbus_initiate_unload()
|
||||||
|
|
||||||
|
We have to call vmbus_initiate_unload() on crash to make kdump work but
|
||||||
|
the crash can also be happening in interrupt (e.g. Sysrq + c results in
|
||||||
|
such) where we can't schedule or the following will happen:
|
||||||
|
|
||||||
|
[ 314.905786] bad: scheduling from the idle thread!
|
||||||
|
|
||||||
|
Just skipping the wait (and even adding some random wait here) won't help:
|
||||||
|
to make host-side magic working we're supposed to receive CHANNELMSG_UNLOAD
|
||||||
|
(and actually confirm the fact that we received it) but we can't use
|
||||||
|
interrupt-base path (vmbus_isr()-> vmbus_on_msg_dpc()). Implement a simple
|
||||||
|
busy wait ignoring all the other messages and use it if we're in an
|
||||||
|
interrupt context.
|
||||||
|
|
||||||
|
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 415719160de3fae3bb9cbc617664649919cd00d0)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 43 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index af1d82e..d6c6114 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -28,6 +28,7 @@
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
#include <linux/hyperv.h>
|
||||||
|
|
||||||
|
#include "hyperv_vmbus.h"
|
||||||
|
@@ -589,6 +590,40 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
|
||||||
|
channel->target_vp = hv_context.vp_index[cur_cpu];
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void vmbus_wait_for_unload(void)
|
||||||
|
+{
|
||||||
|
+ 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 vmbus_channel_message_header *hdr;
|
||||||
|
+ bool unloaded = false;
|
||||||
|
+
|
||||||
|
+ while (1) {
|
||||||
|
+ if (msg->header.message_type == HVMSG_NONE) {
|
||||||
|
+ mdelay(10);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hdr = (struct vmbus_channel_message_header *)msg->u.payload;
|
||||||
|
+ if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
|
||||||
|
+ unloaded = true;
|
||||||
|
+
|
||||||
|
+ msg->header.message_type = HVMSG_NONE;
|
||||||
|
+ /*
|
||||||
|
+ * header.message_type needs to be written before we do
|
||||||
|
+ * wrmsrl() below.
|
||||||
|
+ */
|
||||||
|
+ mb();
|
||||||
|
+
|
||||||
|
+ if (msg->header.message_flags.msg_pending)
|
||||||
|
+ wrmsrl(HV_X64_MSR_EOM, 0);
|
||||||
|
+
|
||||||
|
+ if (unloaded)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* vmbus_unload_response - Handler for the unload response.
|
||||||
|
*/
|
||||||
|
@@ -614,7 +649,14 @@ void vmbus_initiate_unload(void)
|
||||||
|
hdr.msgtype = CHANNELMSG_UNLOAD;
|
||||||
|
vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header));
|
||||||
|
|
||||||
|
- wait_for_completion(&vmbus_connection.unload_event);
|
||||||
|
+ /*
|
||||||
|
+ * vmbus_initiate_unload() is also called on crash and the crash can be
|
||||||
|
+ * happening in an interrupt context, where scheduling is impossible.
|
||||||
|
+ */
|
||||||
|
+ if (!in_interrupt())
|
||||||
|
+ wait_for_completion(&vmbus_connection.unload_event);
|
||||||
|
+ else
|
||||||
|
+ vmbus_wait_for_unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 38bad476ce53b8b305d5629cfa5fe013c82f5a97 Mon Sep 17 00:00:00 2001
|
From 73d794b62769667baebc92515da11aa2ef687bf3 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:37 -0800
|
Date: Wed, 27 Jan 2016 22:29:37 -0800
|
||||||
Subject: [PATCH 15/28] Drivers: hv: vmbus: add a helper function to set a
|
Subject: [PATCH 24/40] Drivers: hv: vmbus: add a helper function to set a
|
||||||
channel's pending send size
|
channel's pending send size
|
||||||
|
|
||||||
This will be used by the coming net/hvsock driver.
|
This will be used by the coming net/hvsock driver.
|
||||||
@ -15,10 +15,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
1 file changed, 6 insertions(+)
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index ae6a711..fda6310 100644
|
index 51c98fd..934542a 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -792,6 +792,12 @@ static inline void *get_per_channel_state(struct vmbus_channel *c)
|
@@ -818,6 +818,12 @@ static inline void *get_per_channel_state(struct vmbus_channel *c)
|
||||||
return c->per_channel_state;
|
return c->per_channel_state;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 34e3731c0ba650cc5e7c15517da15f76e438b031 Mon Sep 17 00:00:00 2001
|
From 57b533b03fea1344ff846c76738cd919678778c1 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:38 -0800
|
Date: Wed, 27 Jan 2016 22:29:38 -0800
|
||||||
Subject: [PATCH 16/28] Drivers: hv: vmbus: define the new offer type for
|
Subject: [PATCH 25/40] Drivers: hv: vmbus: define the new offer type for
|
||||||
Hyper-V socket (hvsock)
|
Hyper-V socket (hvsock)
|
||||||
|
|
||||||
A helper function is also added.
|
A helper function is also added.
|
||||||
@ -15,7 +15,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
1 file changed, 7 insertions(+)
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index fda6310..9fb2130 100644
|
index 934542a..a4f105d 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -237,6 +237,7 @@ struct vmbus_channel_offer {
|
@@ -237,6 +237,7 @@ struct vmbus_channel_offer {
|
||||||
@ -26,7 +26,7 @@ index fda6310..9fb2130 100644
|
|||||||
|
|
||||||
struct vmpacket_descriptor {
|
struct vmpacket_descriptor {
|
||||||
u16 type;
|
u16 type;
|
||||||
@@ -771,6 +772,12 @@ struct vmbus_channel {
|
@@ -797,6 +798,12 @@ struct vmbus_channel {
|
||||||
enum hv_signal_policy signal_policy;
|
enum hv_signal_policy signal_policy;
|
||||||
};
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 53e57822a7f9d6c6fc221c21cfbbe9da2965c059 Mon Sep 17 00:00:00 2001
|
From 3f1df935d1b5caad3f00a43eb50714375bc32547 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:39 -0800
|
Date: Wed, 27 Jan 2016 22:29:39 -0800
|
||||||
Subject: [PATCH 17/28] Drivers: hv: vmbus: vmbus_sendpacket_ctl: hvsock: avoid
|
Subject: [PATCH 26/40] Drivers: hv: vmbus: vmbus_sendpacket_ctl: hvsock: avoid
|
||||||
unnecessary signaling
|
unnecessary signaling
|
||||||
|
|
||||||
When the hvsock channel's outbound ringbuffer is full (i.e.,
|
When the hvsock channel's outbound ringbuffer is full (i.e.,
|
||||||
@ -17,7 +17,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||||
index 2889d97..a7f9e3e 100644
|
index dd6de7f..128dcf2 100644
|
||||||
--- a/drivers/hv/channel.c
|
--- a/drivers/hv/channel.c
|
||||||
+++ b/drivers/hv/channel.c
|
+++ b/drivers/hv/channel.c
|
||||||
@@ -659,6 +659,9 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
@@ -659,6 +659,9 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
@ -1,7 +1,7 @@
|
|||||||
From 7e8defd74db9d20fc2c1b98946f5f1e5ad96e33c Mon Sep 17 00:00:00 2001
|
From 75650dcb326987e017209a61107f341447a88de5 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:40 -0800
|
Date: Wed, 27 Jan 2016 22:29:40 -0800
|
||||||
Subject: [PATCH 18/28] Drivers: hv: vmbus: define a new VMBus message type for
|
Subject: [PATCH 27/40] Drivers: hv: vmbus: define a new VMBus message type for
|
||||||
hvsock
|
hvsock
|
||||||
|
|
||||||
A function to send the type of message is also added.
|
A function to send the type of message is also added.
|
||||||
@ -20,7 +20,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
3 files changed, 32 insertions(+)
|
3 files changed, 32 insertions(+)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||||
index a7f9e3e..239b072 100644
|
index 128dcf2..415f6c7 100644
|
||||||
--- a/drivers/hv/channel.c
|
--- a/drivers/hv/channel.c
|
||||||
+++ b/drivers/hv/channel.c
|
+++ b/drivers/hv/channel.c
|
||||||
@@ -219,6 +219,21 @@ error0:
|
@@ -219,6 +219,21 @@ error0:
|
||||||
@ -46,10 +46,10 @@ index a7f9e3e..239b072 100644
|
|||||||
* create_gpadl_header - Creates a gpadl for the specified buffer
|
* create_gpadl_header - Creates a gpadl for the specified buffer
|
||||||
*/
|
*/
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index bd4f084..4d61f41 100644
|
index d6c6114..60ca25b 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -820,6 +820,10 @@ struct vmbus_channel_message_table_entry
|
@@ -958,6 +958,10 @@ struct vmbus_channel_message_table_entry
|
||||||
{CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response},
|
{CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response},
|
||||||
{CHANNELMSG_UNLOAD, 0, NULL},
|
{CHANNELMSG_UNLOAD, 0, NULL},
|
||||||
{CHANNELMSG_UNLOAD_RESPONSE, 1, vmbus_unload_response},
|
{CHANNELMSG_UNLOAD_RESPONSE, 1, vmbus_unload_response},
|
||||||
@ -61,7 +61,7 @@ index bd4f084..4d61f41 100644
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index 9fb2130..3f485a4 100644
|
index a4f105d..191bc5d 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -394,6 +394,10 @@ enum vmbus_channel_message_type {
|
@@ -394,6 +394,10 @@ enum vmbus_channel_message_type {
|
||||||
@ -89,7 +89,7 @@ index 9fb2130..3f485a4 100644
|
|||||||
struct vmbus_channel_version_response {
|
struct vmbus_channel_version_response {
|
||||||
struct vmbus_channel_message_header header;
|
struct vmbus_channel_message_header header;
|
||||||
u8 version_supported;
|
u8 version_supported;
|
||||||
@@ -1276,4 +1287,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
@@ -1295,4 +1306,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
||||||
|
|
||||||
extern __u32 vmbus_proto_version;
|
extern __u32 vmbus_proto_version;
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 1d19451adec149cefc135c442b4cb2241d87607a Mon Sep 17 00:00:00 2001
|
From f32ca7e520ca07ec5294e852248522c3ac0d145f Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:41 -0800
|
Date: Wed, 27 Jan 2016 22:29:41 -0800
|
||||||
Subject: [PATCH 19/28] Drivers: hv: vmbus: add a hvsock flag in struct
|
Subject: [PATCH 28/40] Drivers: hv: vmbus: add a hvsock flag in struct
|
||||||
hv_driver
|
hv_driver
|
||||||
|
|
||||||
Only the coming hv_sock driver has a "true" value for this flag.
|
Only the coming hv_sock driver has a "true" value for this flag.
|
||||||
@ -20,10 +20,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
2 files changed, 18 insertions(+)
|
2 files changed, 18 insertions(+)
|
||||||
|
|
||||||
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
index 7e46a48..7d607ad 100644
|
index 3b83dfe..d76a65f 100644
|
||||||
--- a/drivers/hv/vmbus_drv.c
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
+++ b/drivers/hv/vmbus_drv.c
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
@@ -563,6 +563,10 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
|
@@ -583,6 +583,10 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
|
||||||
struct hv_driver *drv = drv_to_hv_drv(driver);
|
struct hv_driver *drv = drv_to_hv_drv(driver);
|
||||||
struct hv_device *hv_dev = device_to_hv_device(device);
|
struct hv_device *hv_dev = device_to_hv_device(device);
|
||||||
|
|
||||||
@ -31,14 +31,14 @@ index 7e46a48..7d607ad 100644
|
|||||||
+ if (is_hvsock_channel(hv_dev->channel))
|
+ if (is_hvsock_channel(hv_dev->channel))
|
||||||
+ return drv->hvsock;
|
+ return drv->hvsock;
|
||||||
+
|
+
|
||||||
if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b))
|
if (hv_vmbus_get_id(drv->id_table, &hv_dev->dev_type))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index 3f485a4..9ee79af 100644
|
index 191bc5d..05966e2 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -966,6 +966,20 @@ extern void vmbus_ontimer(unsigned long data);
|
@@ -992,6 +992,20 @@ extern void vmbus_ontimer(unsigned long data);
|
||||||
struct hv_driver {
|
struct hv_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
From 89a360504f1683d1be642506a14c9f59ea2c9771 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rolf Neugebauer <rolf.neugebauer@gmail.com>
|
|
||||||
Date: Sun, 15 May 2016 10:56:16 +0100
|
|
||||||
Subject: [PATCH 28/28] hv_sock: Don't touch the socket state when the other
|
|
||||||
end closes
|
|
||||||
|
|
||||||
This cause a NULL pointer de-reference when the client closes the connection
|
|
||||||
before accept() is called by the server.
|
|
||||||
|
|
||||||
Signed-off-by: Rolf Neugebauer <rolf.neugebauer@gmail.com>
|
|
||||||
---
|
|
||||||
net/hv_sock/af_hvsock.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c
|
|
||||||
index 013d684..0b7ab8a 100644
|
|
||||||
--- a/net/hv_sock/af_hvsock.c
|
|
||||||
+++ b/net/hv_sock/af_hvsock.c
|
|
||||||
@@ -616,7 +616,6 @@ static void hvsock_close_connection(struct vmbus_channel *channel)
|
|
||||||
if (!sk)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
- sk->sk_socket->state = SS_UNCONNECTED;
|
|
||||||
sk->sk_state = SS_UNCONNECTED;
|
|
||||||
sock_set_flag(sk, SOCK_DONE);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.8.2
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 14935b1d81d62a8aee055d8b762a745338e445b2 Mon Sep 17 00:00:00 2001
|
From 91bc38269cbba8c6ffc4db837f22267f72cfcd35 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:42 -0800
|
Date: Wed, 27 Jan 2016 22:29:42 -0800
|
||||||
Subject: [PATCH 20/28] Drivers: hv: vmbus: add a per-channel rescind callback
|
Subject: [PATCH 29/40] Drivers: hv: vmbus: add a per-channel rescind callback
|
||||||
|
|
||||||
This will be used by the coming hv_sock driver.
|
This will be used by the coming hv_sock driver.
|
||||||
|
|
||||||
@ -15,10 +15,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
2 files changed, 20 insertions(+)
|
2 files changed, 20 insertions(+)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index 4d61f41..421e3dd 100644
|
index 60ca25b..76864c9 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -603,6 +603,10 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -741,6 +741,10 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
spin_unlock_irqrestore(&channel->lock, flags);
|
spin_unlock_irqrestore(&channel->lock, flags);
|
||||||
|
|
||||||
if (channel->device_obj) {
|
if (channel->device_obj) {
|
||||||
@ -29,7 +29,7 @@ index 4d61f41..421e3dd 100644
|
|||||||
/*
|
/*
|
||||||
* We will have to unregister this device from the
|
* We will have to unregister this device from the
|
||||||
* driver core.
|
* driver core.
|
||||||
@@ -972,3 +976,10 @@ bool vmbus_are_subchannels_present(struct vmbus_channel *primary)
|
@@ -1110,3 +1114,10 @@ bool vmbus_are_subchannels_present(struct vmbus_channel *primary)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present);
|
EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present);
|
||||||
@ -41,10 +41,10 @@ index 4d61f41..421e3dd 100644
|
|||||||
+}
|
+}
|
||||||
+EXPORT_SYMBOL_GPL(vmbus_set_chn_rescind_callback);
|
+EXPORT_SYMBOL_GPL(vmbus_set_chn_rescind_callback);
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index 9ee79af..09e9ec1 100644
|
index 05966e2..ad04017 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -742,6 +742,12 @@ struct vmbus_channel {
|
@@ -768,6 +768,12 @@ struct vmbus_channel {
|
||||||
void (*sc_creation_callback)(struct vmbus_channel *new_sc);
|
void (*sc_creation_callback)(struct vmbus_channel *new_sc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -57,7 +57,7 @@ index 9ee79af..09e9ec1 100644
|
|||||||
* The spinlock to protect the structure. It is being used to protect
|
* The spinlock to protect the structure. It is being used to protect
|
||||||
* test-and-set access to various attributes of the structure as well
|
* test-and-set access to various attributes of the structure as well
|
||||||
* as all sc_list operations.
|
* as all sc_list operations.
|
||||||
@@ -827,6 +833,9 @@ int vmbus_request_offers(void);
|
@@ -853,6 +859,9 @@ int vmbus_request_offers(void);
|
||||||
void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
|
void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
|
||||||
void (*sc_cr_cb)(struct vmbus_channel *new_sc));
|
void (*sc_cr_cb)(struct vmbus_channel *new_sc));
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 080b343d4e73684e9c261350703a48771eeda231 Mon Sep 17 00:00:00 2001
|
From 5ffa6fad55eaaa00feecefe483a7eb3aba155ae9 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 27 Jan 2016 22:29:43 -0800
|
Date: Wed, 27 Jan 2016 22:29:43 -0800
|
||||||
Subject: [PATCH 21/28] Drivers: hv: vmbus: add an API
|
Subject: [PATCH 30/40] Drivers: hv: vmbus: add an API
|
||||||
vmbus_hvsock_device_unregister()
|
vmbus_hvsock_device_unregister()
|
||||||
|
|
||||||
The hvsock driver needs this API to release all the resources related
|
The hvsock driver needs this API to release all the resources related
|
||||||
@ -18,10 +18,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|||||||
3 files changed, 32 insertions(+), 7 deletions(-)
|
3 files changed, 32 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
index 421e3dd..0fe9665 100644
|
index 76864c9..cf311be 100644
|
||||||
--- a/drivers/hv/channel_mgmt.c
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
+++ b/drivers/hv/channel_mgmt.c
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
@@ -195,6 +195,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
@@ -310,6 +310,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||||
vmbus_release_relid(relid);
|
vmbus_release_relid(relid);
|
||||||
|
|
||||||
BUG_ON(!channel->rescind);
|
BUG_ON(!channel->rescind);
|
||||||
@ -29,7 +29,7 @@ index 421e3dd..0fe9665 100644
|
|||||||
|
|
||||||
if (channel->target_cpu != get_cpu()) {
|
if (channel->target_cpu != get_cpu()) {
|
||||||
put_cpu();
|
put_cpu();
|
||||||
@@ -206,9 +207,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
@@ -321,9 +322,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel->primary_channel == NULL) {
|
if (channel->primary_channel == NULL) {
|
||||||
@ -39,15 +39,15 @@ index 421e3dd..0fe9665 100644
|
|||||||
|
|
||||||
primary_channel = channel;
|
primary_channel = channel;
|
||||||
} else {
|
} else {
|
||||||
@@ -251,6 +250,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
@@ -367,6 +366,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
struct vmbus_channel *channel;
|
|
||||||
bool fnew = true;
|
bool fnew = true;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
u16 dev_type;
|
||||||
+ int ret;
|
+ int ret;
|
||||||
|
|
||||||
/* Make sure this is a new offer */
|
/* Make sure this is a new offer */
|
||||||
mutex_lock(&vmbus_connection.channel_mutex);
|
mutex_lock(&vmbus_connection.channel_mutex);
|
||||||
@@ -330,7 +330,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
@@ -449,7 +449,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
* binding which eventually invokes the device driver's AddDevice()
|
* binding which eventually invokes the device driver's AddDevice()
|
||||||
* method.
|
* method.
|
||||||
*/
|
*/
|
||||||
@ -60,7 +60,7 @@ index 421e3dd..0fe9665 100644
|
|||||||
pr_err("unable to add child device object (relid %d)\n",
|
pr_err("unable to add child device object (relid %d)\n",
|
||||||
newchannel->offermsg.child_relid);
|
newchannel->offermsg.child_relid);
|
||||||
kfree(newchannel->device_obj);
|
kfree(newchannel->device_obj);
|
||||||
@@ -587,6 +591,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -725,6 +729,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
rescind = (struct vmbus_channel_rescind_offer *)hdr;
|
rescind = (struct vmbus_channel_rescind_offer *)hdr;
|
||||||
@ -69,7 +69,7 @@ index 421e3dd..0fe9665 100644
|
|||||||
channel = relid2channel(rescind->child_relid);
|
channel = relid2channel(rescind->child_relid);
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
@@ -595,7 +601,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -733,7 +739,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
* vmbus_process_offer(), we have already invoked
|
* vmbus_process_offer(), we have already invoked
|
||||||
* vmbus_release_relid() on error.
|
* vmbus_release_relid() on error.
|
||||||
*/
|
*/
|
||||||
@ -78,7 +78,7 @@ index 421e3dd..0fe9665 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&channel->lock, flags);
|
spin_lock_irqsave(&channel->lock, flags);
|
||||||
@@ -605,7 +611,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -743,7 +749,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
if (channel->device_obj) {
|
if (channel->device_obj) {
|
||||||
if (channel->chn_rescind_callback) {
|
if (channel->chn_rescind_callback) {
|
||||||
channel->chn_rescind_callback(channel);
|
channel->chn_rescind_callback(channel);
|
||||||
@ -87,7 +87,7 @@ index 421e3dd..0fe9665 100644
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* We will have to unregister this device from the
|
* We will have to unregister this device from the
|
||||||
@@ -620,8 +626,25 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
@@ -758,8 +764,25 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||||
hv_process_channel_removal(channel,
|
hv_process_channel_removal(channel,
|
||||||
channel->offermsg.child_relid);
|
channel->offermsg.child_relid);
|
||||||
}
|
}
|
||||||
@ -136,10 +136,10 @@ index 521f48e..09c08b5 100644
|
|||||||
return found_channel;
|
return found_channel;
|
||||||
}
|
}
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index 09e9ec1..af7ee0a 100644
|
index ad04017..993318a 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -1043,6 +1043,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
|
@@ -1071,6 +1071,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
|
||||||
const char *mod_name);
|
const char *mod_name);
|
||||||
void vmbus_driver_unregister(struct hv_driver *hv_driver);
|
void vmbus_driver_unregister(struct hv_driver *hv_driver);
|
||||||
|
|
@ -0,0 +1,208 @@
|
|||||||
|
From e648c3f4c7a150cec1c794037af051c671358d18 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||||
|
Date: Wed, 27 Jan 2016 22:29:45 -0800
|
||||||
|
Subject: [PATCH 31/40] Drivers: hv: vmbus: Give control over how the ring
|
||||||
|
access is serialized
|
||||||
|
|
||||||
|
On the channel send side, many of the VMBUS
|
||||||
|
device drivers explicity serialize access to the
|
||||||
|
outgoing ring buffer. Give more control to the
|
||||||
|
VMBUS device drivers in terms how to serialize
|
||||||
|
accesss to the outgoing ring buffer.
|
||||||
|
The default behavior will be to aquire the
|
||||||
|
ring lock to preserve the current behavior.
|
||||||
|
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit fe760e4d64fe5c17c39e86c410d41f6587ee88bc)
|
||||||
|
---
|
||||||
|
drivers/hv/channel.c | 15 +++++++++++----
|
||||||
|
drivers/hv/channel_mgmt.c | 1 +
|
||||||
|
drivers/hv/hyperv_vmbus.h | 2 +-
|
||||||
|
drivers/hv/ring_buffer.c | 13 ++++++++-----
|
||||||
|
include/linux/hyperv.h | 16 ++++++++++++++++
|
||||||
|
5 files changed, 37 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||||
|
index 415f6c7..57a1b65 100644
|
||||||
|
--- a/drivers/hv/channel.c
|
||||||
|
+++ b/drivers/hv/channel.c
|
||||||
|
@@ -639,6 +639,7 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||||
|
u64 aligned_data = 0;
|
||||||
|
int ret;
|
||||||
|
bool signal = false;
|
||||||
|
+ bool lock = channel->acquire_ring_lock;
|
||||||
|
int num_vecs = ((bufferlen != 0) ? 3 : 1);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -658,7 +659,7 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||||
|
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||||
|
|
||||||
|
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
|
||||||
|
- &signal);
|
||||||
|
+ &signal, lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signalling the host is conditional on many factors:
|
||||||
|
@@ -738,6 +739,7 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||||
|
struct kvec bufferlist[3];
|
||||||
|
u64 aligned_data = 0;
|
||||||
|
bool signal = false;
|
||||||
|
+ bool lock = channel->acquire_ring_lock;
|
||||||
|
|
||||||
|
if (pagecount > MAX_PAGE_BUFFER_COUNT)
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -774,7 +776,8 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||||
|
bufferlist[2].iov_base = &aligned_data;
|
||||||
|
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||||
|
|
||||||
|
- ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
|
||||||
|
+ ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
|
||||||
|
+ &signal, lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signalling the host is conditional on many factors:
|
||||||
|
@@ -837,6 +840,7 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
|
||||||
|
struct kvec bufferlist[3];
|
||||||
|
u64 aligned_data = 0;
|
||||||
|
bool signal = false;
|
||||||
|
+ bool lock = channel->acquire_ring_lock;
|
||||||
|
|
||||||
|
packetlen = desc_size + bufferlen;
|
||||||
|
packetlen_aligned = ALIGN(packetlen, sizeof(u64));
|
||||||
|
@@ -856,7 +860,8 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
|
||||||
|
bufferlist[2].iov_base = &aligned_data;
|
||||||
|
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||||
|
|
||||||
|
- ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
|
||||||
|
+ ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
|
||||||
|
+ &signal, lock);
|
||||||
|
|
||||||
|
if (ret == 0 && signal)
|
||||||
|
vmbus_setevent(channel);
|
||||||
|
@@ -881,6 +886,7 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
|
||||||
|
struct kvec bufferlist[3];
|
||||||
|
u64 aligned_data = 0;
|
||||||
|
bool signal = false;
|
||||||
|
+ bool lock = channel->acquire_ring_lock;
|
||||||
|
u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
|
||||||
|
multi_pagebuffer->len);
|
||||||
|
|
||||||
|
@@ -919,7 +925,8 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
|
||||||
|
bufferlist[2].iov_base = &aligned_data;
|
||||||
|
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||||
|
|
||||||
|
- ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
|
||||||
|
+ ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
|
||||||
|
+ &signal, lock);
|
||||||
|
|
||||||
|
if (ret == 0 && signal)
|
||||||
|
vmbus_setevent(channel);
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index cf311be..b40f429 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -259,6 +259,7 @@ static struct vmbus_channel *alloc_channel(void)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
channel->id = atomic_inc_return(&chan_num);
|
||||||
|
+ channel->acquire_ring_lock = true;
|
||||||
|
spin_lock_init(&channel->inbound_lock);
|
||||||
|
spin_lock_init(&channel->lock);
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||||
|
index d9937be..b925fa3 100644
|
||||||
|
--- a/drivers/hv/hyperv_vmbus.h
|
||||||
|
+++ b/drivers/hv/hyperv_vmbus.h
|
||||||
|
@@ -612,7 +612,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
|
||||||
|
|
||||||
|
int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
|
||||||
|
struct kvec *kv_list,
|
||||||
|
- u32 kv_count, bool *signal);
|
||||||
|
+ u32 kv_count, bool *signal, bool lock);
|
||||||
|
|
||||||
|
int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
|
||||||
|
u32 buflen);
|
||||||
|
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
|
||||||
|
index 70a1a9a..89a428f 100644
|
||||||
|
--- a/drivers/hv/ring_buffer.c
|
||||||
|
+++ b/drivers/hv/ring_buffer.c
|
||||||
|
@@ -388,7 +388,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||||
|
- struct kvec *kv_list, u32 kv_count, bool *signal)
|
||||||
|
+ struct kvec *kv_list, u32 kv_count, bool *signal, bool lock)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
u32 bytes_avail_towrite;
|
||||||
|
@@ -398,14 +398,15 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||||
|
u32 next_write_location;
|
||||||
|
u32 old_write;
|
||||||
|
u64 prev_indices = 0;
|
||||||
|
- unsigned long flags;
|
||||||
|
+ unsigned long flags = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < kv_count; i++)
|
||||||
|
totalbytes_towrite += kv_list[i].iov_len;
|
||||||
|
|
||||||
|
totalbytes_towrite += sizeof(u64);
|
||||||
|
|
||||||
|
- spin_lock_irqsave(&outring_info->ring_lock, flags);
|
||||||
|
+ if (lock)
|
||||||
|
+ spin_lock_irqsave(&outring_info->ring_lock, flags);
|
||||||
|
|
||||||
|
hv_get_ringbuffer_availbytes(outring_info,
|
||||||
|
&bytes_avail_toread,
|
||||||
|
@@ -416,7 +417,8 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||||
|
/* 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);
|
||||||
|
+ if (lock)
|
||||||
|
+ spin_unlock_irqrestore(&outring_info->ring_lock, flags);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -447,7 +449,8 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||||
|
hv_set_next_write_location(outring_info, next_write_location);
|
||||||
|
|
||||||
|
|
||||||
|
- spin_unlock_irqrestore(&outring_info->ring_lock, flags);
|
||||||
|
+ if (lock)
|
||||||
|
+ spin_unlock_irqrestore(&outring_info->ring_lock, flags);
|
||||||
|
|
||||||
|
*signal = hv_need_to_signal(old_write, outring_info);
|
||||||
|
return 0;
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index 993318a..6c9695e 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -813,8 +813,24 @@ struct vmbus_channel {
|
||||||
|
* signaling control.
|
||||||
|
*/
|
||||||
|
enum hv_signal_policy signal_policy;
|
||||||
|
+ /*
|
||||||
|
+ * On the channel send side, many of the VMBUS
|
||||||
|
+ * device drivers explicity serialize access to the
|
||||||
|
+ * outgoing ring buffer. Give more control to the
|
||||||
|
+ * VMBUS device drivers in terms how to serialize
|
||||||
|
+ * accesss to the outgoing ring buffer.
|
||||||
|
+ * The default behavior will be to aquire the
|
||||||
|
+ * ring lock to preserve the current behavior.
|
||||||
|
+ */
|
||||||
|
+ bool acquire_ring_lock;
|
||||||
|
+
|
||||||
|
};
|
||||||
|
|
||||||
|
+static inline void set_channel_lock_state(struct vmbus_channel *c, bool state)
|
||||||
|
+{
|
||||||
|
+ c->acquire_ring_lock = state;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline bool is_hvsock_channel(const struct vmbus_channel *c)
|
||||||
|
{
|
||||||
|
return !!(c->offermsg.offer.chn_flags &
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,100 @@
|
|||||||
|
From 801ca93a137e97e204c04bf648901f73d38fabc9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Date: Fri, 26 Feb 2016 15:13:16 -0800
|
||||||
|
Subject: [PATCH 32/40] Drivers: hv: vmbus: avoid wait_for_completion() on
|
||||||
|
crash
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
wait_for_completion() may sleep, it enables interrupts and this
|
||||||
|
is something we really want to avoid on crashes because interrupt
|
||||||
|
handlers can cause other crashes. Switch to the recently introduced
|
||||||
|
vmbus_wait_for_unload() doing busy wait instead.
|
||||||
|
|
||||||
|
Reported-by: Radim Krcmar <rkrcmar@redhat.com>
|
||||||
|
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit 75ff3a8a9168df750b5bd0589e897a6c0517a9f1)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 4 ++--
|
||||||
|
drivers/hv/connection.c | 2 +-
|
||||||
|
drivers/hv/hyperv_vmbus.h | 2 +-
|
||||||
|
drivers/hv/vmbus_drv.c | 4 ++--
|
||||||
|
4 files changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index b40f429..f70e352 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -641,7 +641,7 @@ static void vmbus_unload_response(struct vmbus_channel_message_header *hdr)
|
||||||
|
complete(&vmbus_connection.unload_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void vmbus_initiate_unload(void)
|
||||||
|
+void vmbus_initiate_unload(bool crash)
|
||||||
|
{
|
||||||
|
struct vmbus_channel_message_header hdr;
|
||||||
|
|
||||||
|
@@ -658,7 +658,7 @@ void vmbus_initiate_unload(void)
|
||||||
|
* vmbus_initiate_unload() is also called on crash and the crash can be
|
||||||
|
* happening in an interrupt context, where scheduling is impossible.
|
||||||
|
*/
|
||||||
|
- if (!in_interrupt())
|
||||||
|
+ if (!crash)
|
||||||
|
wait_for_completion(&vmbus_connection.unload_event);
|
||||||
|
else
|
||||||
|
vmbus_wait_for_unload();
|
||||||
|
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
|
||||||
|
index 09c08b5..78b8be8 100644
|
||||||
|
--- a/drivers/hv/connection.c
|
||||||
|
+++ b/drivers/hv/connection.c
|
||||||
|
@@ -233,7 +233,7 @@ void vmbus_disconnect(void)
|
||||||
|
/*
|
||||||
|
* First send the unload request to the host.
|
||||||
|
*/
|
||||||
|
- vmbus_initiate_unload();
|
||||||
|
+ vmbus_initiate_unload(false);
|
||||||
|
|
||||||
|
if (vmbus_connection.work_queue) {
|
||||||
|
drain_workqueue(vmbus_connection.work_queue);
|
||||||
|
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||||
|
index b925fa3..10efab0 100644
|
||||||
|
--- a/drivers/hv/hyperv_vmbus.h
|
||||||
|
+++ b/drivers/hv/hyperv_vmbus.h
|
||||||
|
@@ -751,7 +751,7 @@ void hv_vss_onchannelcallback(void *);
|
||||||
|
int hv_fcopy_init(struct hv_util_service *);
|
||||||
|
void hv_fcopy_deinit(void);
|
||||||
|
void hv_fcopy_onchannelcallback(void *);
|
||||||
|
-void vmbus_initiate_unload(void);
|
||||||
|
+void vmbus_initiate_unload(bool crash);
|
||||||
|
|
||||||
|
static inline void hv_poll_channel(struct vmbus_channel *channel,
|
||||||
|
void (*cb)(void *))
|
||||||
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||||
|
index d76a65f..45ea71e 100644
|
||||||
|
--- a/drivers/hv/vmbus_drv.c
|
||||||
|
+++ b/drivers/hv/vmbus_drv.c
|
||||||
|
@@ -1263,7 +1263,7 @@ static void hv_kexec_handler(void)
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
hv_synic_clockevents_cleanup();
|
||||||
|
- vmbus_initiate_unload();
|
||||||
|
+ vmbus_initiate_unload(false);
|
||||||
|
for_each_online_cpu(cpu)
|
||||||
|
smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
|
||||||
|
hv_cleanup();
|
||||||
|
@@ -1271,7 +1271,7 @@ static void hv_kexec_handler(void)
|
||||||
|
|
||||||
|
static void hv_crash_handler(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
- vmbus_initiate_unload();
|
||||||
|
+ vmbus_initiate_unload(true);
|
||||||
|
/*
|
||||||
|
* In crash handler we can't schedule synic cleanup for all CPUs,
|
||||||
|
* doing the cleanup for current CPU only. This should be sufficient
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 57ebe7b218a4293879c6cfcfc809bd28d1c86d0b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Date: Fri, 26 Feb 2016 15:13:18 -0800
|
||||||
|
Subject: [PATCH 33/40] Drivers: hv: vmbus: avoid unneeded compiler
|
||||||
|
optimizations in vmbus_wait_for_unload()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Message header is modified by the hypervisor and we read it in a loop,
|
||||||
|
we need to prevent compilers from optimizing accesses. There are no such
|
||||||
|
optimizations at this moment, this is just a future proof.
|
||||||
|
|
||||||
|
Suggested-by: Radim Krcmar <rkrcmar@redhat.com>
|
||||||
|
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
|
||||||
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
|
(cherry picked from commit d452ab7b4c65dfcaee88a0d6866eeeb98a3d1884)
|
||||||
|
---
|
||||||
|
drivers/hv/channel_mgmt.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index f70e352..c892db5 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -605,7 +605,7 @@ static void vmbus_wait_for_unload(void)
|
||||||
|
bool unloaded = false;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
- if (msg->header.message_type == HVMSG_NONE) {
|
||||||
|
+ if (READ_ONCE(msg->header.message_type) == HVMSG_NONE) {
|
||||||
|
mdelay(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 7f7ff16a50fdab9cf540ba469dd4fd9dc1c36ce8 Mon Sep 17 00:00:00 2001
|
From 309de4588761836db8325d18c96048c1d57976b0 Mon Sep 17 00:00:00 2001
|
||||||
From: Tom Herbert <tom@herbertland.com>
|
From: Tom Herbert <tom@herbertland.com>
|
||||||
Date: Mon, 7 Mar 2016 14:11:06 -0800
|
Date: Mon, 7 Mar 2016 14:11:06 -0800
|
||||||
Subject: [PATCH 22/28] kcm: Kernel Connection Multiplexor module
|
Subject: [PATCH 34/40] kcm: Kernel Connection Multiplexor module
|
||||||
|
|
||||||
This module implements the Kernel Connection Multiplexor.
|
This module implements the Kernel Connection Multiplexor.
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 0f2c256a5c2d11572adb078202575c85472c23dd Mon Sep 17 00:00:00 2001
|
From 1b288c812adaffa34be2dc691e559a2c1ba343fa Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 21 Mar 2016 02:51:09 -0700
|
Date: Mon, 21 Mar 2016 02:51:09 -0700
|
||||||
Subject: [PATCH 23/28] net: add the AF_KCM entries to family name tables
|
Subject: [PATCH 35/40] net: add the AF_KCM entries to family name tables
|
||||||
|
|
||||||
This is for the recent kcm driver, which introduces AF_KCM(41) in
|
This is for the recent kcm driver, which introduces AF_KCM(41) in
|
||||||
b7ac4eb(kcm: Kernel Connection Multiplexor module).
|
b7ac4eb(kcm: Kernel Connection Multiplexor module).
|
@ -1,7 +1,7 @@
|
|||||||
From ff301a551f581af1f7a5b44e531f24f6706ff8a1 Mon Sep 17 00:00:00 2001
|
From 2bc2ef5b66204e811990746ae362acd16519b35d Mon Sep 17 00:00:00 2001
|
||||||
From: Courtney Cavin <courtney.cavin@sonymobile.com>
|
From: Courtney Cavin <courtney.cavin@sonymobile.com>
|
||||||
Date: Wed, 27 Apr 2016 12:13:03 -0700
|
Date: Wed, 27 Apr 2016 12:13:03 -0700
|
||||||
Subject: [PATCH 24/28] net: Add Qualcomm IPC router
|
Subject: [PATCH 36/40] net: Add Qualcomm IPC router
|
||||||
|
|
||||||
Add an implementation of Qualcomm's IPC router protocol, used to
|
Add an implementation of Qualcomm's IPC router protocol, used to
|
||||||
communicate with service providing remote processors.
|
communicate with service providing remote processors.
|
@ -1,7 +1,7 @@
|
|||||||
From f94eeafa1082af0972a429ca973da5230e21c5c9 Mon Sep 17 00:00:00 2001
|
From e40aa678ad8d502eb916a28f5f3c35c162dcf4d2 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Wed, 11 May 2016 10:52:37 -0700
|
Date: Sun, 15 May 2016 09:53:11 -0700
|
||||||
Subject: [PATCH 25/28] hv_sock: introduce Hyper-V Sockets
|
Subject: [PATCH 37/40] hv_sock: introduce Hyper-V Sockets
|
||||||
|
|
||||||
Hyper-V Sockets (hv_sock) supplies a byte-stream based communication
|
Hyper-V Sockets (hv_sock) supplies a byte-stream based communication
|
||||||
mechanism between the host and the guest. It's somewhat like TCP over
|
mechanism between the host and the guest. It's somewhat like TCP over
|
||||||
@ -22,7 +22,7 @@ Cc: "K. Y. Srinivasan" <kys@microsoft.com>
|
|||||||
Cc: Haiyang Zhang <haiyangz@microsoft.com>
|
Cc: Haiyang Zhang <haiyangz@microsoft.com>
|
||||||
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
|
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
Cc: Cathy Avery <cavery@redhat.com>
|
Cc: Cathy Avery <cavery@redhat.com>
|
||||||
Origin: http://patchwork.ozlabs.org/patch/621190/
|
Origin: https://patchwork.ozlabs.org/patch/622404/
|
||||||
---
|
---
|
||||||
MAINTAINERS | 2 +
|
MAINTAINERS | 2 +
|
||||||
include/linux/hyperv.h | 14 +
|
include/linux/hyperv.h | 14 +
|
||||||
@ -33,8 +33,8 @@ Origin: http://patchwork.ozlabs.org/patch/621190/
|
|||||||
net/Makefile | 1 +
|
net/Makefile | 1 +
|
||||||
net/hv_sock/Kconfig | 10 +
|
net/hv_sock/Kconfig | 10 +
|
||||||
net/hv_sock/Makefile | 3 +
|
net/hv_sock/Makefile | 3 +
|
||||||
net/hv_sock/af_hvsock.c | 1484 +++++++++++++++++++++++++++++++++++++++++++
|
net/hv_sock/af_hvsock.c | 1520 +++++++++++++++++++++++++++++++++++++++++++
|
||||||
10 files changed, 1621 insertions(+), 1 deletion(-)
|
10 files changed, 1657 insertions(+), 1 deletion(-)
|
||||||
create mode 100644 include/net/af_hvsock.h
|
create mode 100644 include/net/af_hvsock.h
|
||||||
create mode 100644 net/hv_sock/Kconfig
|
create mode 100644 net/hv_sock/Kconfig
|
||||||
create mode 100644 net/hv_sock/Makefile
|
create mode 100644 net/hv_sock/Makefile
|
||||||
@ -55,10 +55,10 @@ index 9a70d2d..1021706 100644
|
|||||||
F: Documentation/ABI/stable/sysfs-bus-vmbus
|
F: Documentation/ABI/stable/sysfs-bus-vmbus
|
||||||
|
|
||||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
index af7ee0a..9864a30 100644
|
index 6c9695e..187d4bd 100644
|
||||||
--- a/include/linux/hyperv.h
|
--- a/include/linux/hyperv.h
|
||||||
+++ b/include/linux/hyperv.h
|
+++ b/include/linux/hyperv.h
|
||||||
@@ -1314,4 +1314,18 @@ extern __u32 vmbus_proto_version;
|
@@ -1349,4 +1349,18 @@ extern __u32 vmbus_proto_version;
|
||||||
|
|
||||||
int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
|
int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
|
||||||
const uuid_le *shv_host_servie_id);
|
const uuid_le *shv_host_servie_id);
|
||||||
@ -102,7 +102,7 @@ index dbd81e7..6634c47 100644
|
|||||||
/* Maximum queue length specifiable by listen. */
|
/* Maximum queue length specifiable by listen. */
|
||||||
diff --git a/include/net/af_hvsock.h b/include/net/af_hvsock.h
|
diff --git a/include/net/af_hvsock.h b/include/net/af_hvsock.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..e002397
|
index 0000000..7c8c41e
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/include/net/af_hvsock.h
|
+++ b/include/net/af_hvsock.h
|
||||||
@@ -0,0 +1,78 @@
|
@@ -0,0 +1,78 @@
|
||||||
@ -113,7 +113,7 @@ index 0000000..e002397
|
|||||||
+#include <linux/hyperv.h>
|
+#include <linux/hyperv.h>
|
||||||
+#include <net/sock.h>
|
+#include <net/sock.h>
|
||||||
+
|
+
|
||||||
+/* Note: 3-page is the minimal recv ringbuffer size:
|
+/* Note: 3-page is the minimal recv ringbuffer size by default:
|
||||||
+ *
|
+ *
|
||||||
+ * the 1st page is used as the shared read/write index etc, rather than data:
|
+ * the 1st page is used as the shared read/write index etc, rather than data:
|
||||||
+ * see hv_ringbuffer_init();
|
+ * see hv_ringbuffer_init();
|
||||||
@ -123,18 +123,18 @@ index 0000000..e002397
|
|||||||
+ * need at least 2 extra pages for ringbuffer data.
|
+ * need at least 2 extra pages for ringbuffer data.
|
||||||
+ */
|
+ */
|
||||||
+#define HVSOCK_RCV_BUF_SZ PAGE_SIZE
|
+#define HVSOCK_RCV_BUF_SZ PAGE_SIZE
|
||||||
+#define VMBUS_RINGBUFFER_SIZE_HVSOCK_RCV (3 * PAGE_SIZE)
|
+#define DEF_RINGBUFFER_PAGES_HVSOCK_RCV 3
|
||||||
+
|
+
|
||||||
+/* As to send, here let's make sure the hvsock_send_buf struct can be held in 1
|
+/* As to send, here let's make sure the hvsock_send_buf struct can be held in 1
|
||||||
+ * page, and since we want to use 2 pages for the send ringbuffer size (this is
|
+ * page, and since we want to use 2 pages for the send ringbuffer size (this is
|
||||||
+ * the minimal size because the 1st page of the two is used as the shared
|
+ * the minimal size by default, because the 1st page of the two is used as the
|
||||||
+ * read/write index etc, rather than data), we only have 1 page for ringbuffer
|
+ * shared read/write index etc, rather than data), we only have 1 page for
|
||||||
+ * data, this means: the max payload length for hvsock data is
|
+ * ringbuffer data, this means: the max payload length for hvsock data is
|
||||||
+ * PAGE_SIZE - HVSOCK_PKT_LEN(0). Finally, let's reduce the length by 8-bytes
|
+ * PAGE_SIZE - HVSOCK_PKT_LEN(0). And, let's reduce the length by 8-bytes
|
||||||
+ * because the ringbuffer can't be 100% full: see hv_ringbuffer_write().
|
+ * because the ringbuffer can't be 100% full: see hv_ringbuffer_write().
|
||||||
+ */
|
+ */
|
||||||
+#define HVSOCK_SND_BUF_SZ (PAGE_SIZE - HVSOCK_PKT_LEN(0) - 8)
|
+#define HVSOCK_SND_BUF_SZ (PAGE_SIZE - HVSOCK_PKT_LEN(0) - 8)
|
||||||
+#define VMBUS_RINGBUFFER_SIZE_HVSOCK_SND (2 * PAGE_SIZE)
|
+#define DEF_RINGBUFFER_PAGES_HVSOCK_SND 2
|
||||||
+
|
+
|
||||||
+/* We only send data when the available space is "big enough". This artificial
|
+/* We only send data when the available space is "big enough". This artificial
|
||||||
+ * value must be less than HVSOCK_SND_BUF_SZ.
|
+ * value must be less than HVSOCK_SND_BUF_SZ.
|
||||||
@ -276,10 +276,10 @@ index 0000000..716c012
|
|||||||
+hv_sock-y += af_hvsock.o
|
+hv_sock-y += af_hvsock.o
|
||||||
diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c
|
diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..013d684
|
index 0000000..b91bd60
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/net/hv_sock/af_hvsock.c
|
+++ b/net/hv_sock/af_hvsock.c
|
||||||
@@ -0,0 +1,1484 @@
|
@@ -0,0 +1,1520 @@
|
||||||
+/*
|
+/*
|
||||||
+ * Hyper-V Sockets -- a socket-based communication channel between the
|
+ * Hyper-V Sockets -- a socket-based communication channel between the
|
||||||
+ * Hyper-V host and the virtual machines running on it.
|
+ * Hyper-V host and the virtual machines running on it.
|
||||||
@ -317,6 +317,21 @@ index 0000000..013d684
|
|||||||
+#include <linux/module.h>
|
+#include <linux/module.h>
|
||||||
+#include <net/af_hvsock.h>
|
+#include <net/af_hvsock.h>
|
||||||
+
|
+
|
||||||
|
+static uint send_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_SND;
|
||||||
|
+static uint recv_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_RCV;
|
||||||
|
+static uint max_socket_number = 1024;
|
||||||
|
+
|
||||||
|
+static atomic_t total_num_hvsock = ATOMIC_INIT(0);
|
||||||
|
+
|
||||||
|
+module_param(send_ring_page, uint, 0444);
|
||||||
|
+MODULE_PARM_DESC(send_ring_page, "Send ring buffer size (# of pages)");
|
||||||
|
+
|
||||||
|
+module_param(recv_ring_page, uint, 0444);
|
||||||
|
+MODULE_PARM_DESC(recv_ring_page, "Receive ring buffer size (# of pages)");
|
||||||
|
+
|
||||||
|
+module_param(max_socket_number, uint, 0644);
|
||||||
|
+MODULE_PARM_DESC(max_socket_number, "The max number of created sockets");
|
||||||
|
+
|
||||||
+static struct proto hvsock_proto = {
|
+static struct proto hvsock_proto = {
|
||||||
+ .name = "HV_SOCK",
|
+ .name = "HV_SOCK",
|
||||||
+ .owner = THIS_MODULE,
|
+ .owner = THIS_MODULE,
|
||||||
@ -525,6 +540,7 @@ index 0000000..013d684
|
|||||||
+
|
+
|
||||||
+ kfree(hvsk->send);
|
+ kfree(hvsk->send);
|
||||||
+ kfree(hvsk->recv);
|
+ kfree(hvsk->recv);
|
||||||
|
+ atomic_dec(&total_num_hvsock);
|
||||||
+
|
+
|
||||||
+ if (!channel)
|
+ if (!channel)
|
||||||
+ return;
|
+ return;
|
||||||
@ -581,43 +597,48 @@ index 0000000..013d684
|
|||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static struct sock *__hvsock_create(struct net *net, struct socket *sock,
|
+static int hvsock_create(struct net *net, struct socket *sock,
|
||||||
+ gfp_t priority, unsigned short type)
|
+ gfp_t priority, unsigned short type,
|
||||||
|
+ struct sock **sk)
|
||||||
+{
|
+{
|
||||||
+ struct hvsock_send_buf *send = NULL;
|
+ struct hvsock_send_buf *send = NULL;
|
||||||
+ struct hvsock_recv_buf *recv = NULL;
|
+ struct hvsock_recv_buf *recv = NULL;
|
||||||
+
|
|
||||||
+ struct hvsock_sock *hvsk;
|
+ struct hvsock_sock *hvsk;
|
||||||
+ struct sock *sk;
|
+ int ret = -EMFILE;
|
||||||
|
+ int num_hvsock;
|
||||||
+
|
+
|
||||||
+ send = kmalloc(sizeof(struct hvsock_send_buf), GFP_KERNEL);
|
+ num_hvsock = atomic_inc_return(&total_num_hvsock);
|
||||||
+ recv = kmalloc(sizeof(struct hvsock_recv_buf), GFP_KERNEL);
|
+ if (num_hvsock > max_socket_number)
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ send = kmalloc(sizeof(*send), GFP_KERNEL);
|
||||||
|
+ recv = kmalloc(sizeof(*recv), GFP_KERNEL);
|
||||||
+ if (!send || !recv)
|
+ if (!send || !recv)
|
||||||
+ goto err;
|
+ goto err;
|
||||||
+
|
+
|
||||||
+ sk = sk_alloc(net, AF_HYPERV, priority, &hvsock_proto, 0);
|
+ *sk = sk_alloc(net, AF_HYPERV, priority, &hvsock_proto, 0);
|
||||||
+ if (!sk)
|
+ if (!*sk)
|
||||||
+ goto err;
|
+ goto err;
|
||||||
+
|
+
|
||||||
+ sock_init_data(sock, sk);
|
+ sock_init_data(sock, *sk);
|
||||||
+
|
+
|
||||||
+ /* sk->sk_type is normally set in sock_init_data, but only if sock is
|
+ /* (*sk)->sk_type is normally set in sock_init_data, but only if sock
|
||||||
+ * non-NULL. We make sure that our sockets always have a type by
|
+ * is non-NULL. We make sure that our sockets always have a type by
|
||||||
+ * setting it here if needed.
|
+ * setting it here if needed.
|
||||||
+ */
|
+ */
|
||||||
+ if (!sock)
|
+ if (!sock)
|
||||||
+ sk->sk_type = type;
|
+ (*sk)->sk_type = type;
|
||||||
+
|
+
|
||||||
+
|
+ (*sk)->sk_destruct = hvsock_sk_destruct;
|
||||||
+ sk->sk_destruct = hvsock_sk_destruct;
|
|
||||||
+
|
+
|
||||||
+ /* Looks stream-based socket doesn't need this. */
|
+ /* Looks stream-based socket doesn't need this. */
|
||||||
+ sk->sk_backlog_rcv = NULL;
|
+ (*sk)->sk_backlog_rcv = NULL;
|
||||||
+
|
+
|
||||||
+ sk->sk_state = 0;
|
+ (*sk)->sk_state = 0;
|
||||||
+ sock_reset_flag(sk, SOCK_DONE);
|
+ sock_reset_flag(*sk, SOCK_DONE);
|
||||||
+
|
+
|
||||||
+ hvsk = sk_to_hvsock(sk);
|
+ hvsk = sk_to_hvsock(*sk);
|
||||||
+
|
+
|
||||||
+ hvsk->send = send;
|
+ hvsk->send = send;
|
||||||
+ hvsk->recv = recv;
|
+ hvsk->recv = recv;
|
||||||
@ -636,11 +657,13 @@ index 0000000..013d684
|
|||||||
+ hvsk->recv->data_len = 0;
|
+ hvsk->recv->data_len = 0;
|
||||||
+ hvsk->recv->data_offset = 0;
|
+ hvsk->recv->data_offset = 0;
|
||||||
+
|
+
|
||||||
+ return sk;
|
+ return 0;
|
||||||
+err:
|
+err:
|
||||||
|
+ atomic_dec(&total_num_hvsock);
|
||||||
+ kfree(send);
|
+ kfree(send);
|
||||||
+ kfree(recv);
|
+ kfree(recv);
|
||||||
+ return NULL;
|
+ *sk = NULL;
|
||||||
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int hvsock_bind(struct socket *sock, struct sockaddr *addr,
|
+static int hvsock_bind(struct socket *sock, struct sockaddr *addr,
|
||||||
@ -699,40 +722,6 @@ index 0000000..013d684
|
|||||||
+ return ret;
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int hvsock_shutdown(struct socket *sock, int mode)
|
|
||||||
+{
|
|
||||||
+ struct sock *sk;
|
|
||||||
+
|
|
||||||
+ if (mode < SHUT_RD || mode > SHUT_RDWR)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ /* This maps:
|
|
||||||
+ * SHUT_RD (0) -> RCV_SHUTDOWN (1)
|
|
||||||
+ * SHUT_WR (1) -> SEND_SHUTDOWN (2)
|
|
||||||
+ * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
|
|
||||||
+ */
|
|
||||||
+ ++mode;
|
|
||||||
+
|
|
||||||
+ if (sock->state == SS_UNCONNECTED)
|
|
||||||
+ return -ENOTCONN;
|
|
||||||
+
|
|
||||||
+ sock->state = SS_DISCONNECTING;
|
|
||||||
+
|
|
||||||
+ sk = sock->sk;
|
|
||||||
+
|
|
||||||
+ lock_sock(sk);
|
|
||||||
+
|
|
||||||
+ sk->sk_shutdown |= mode;
|
|
||||||
+ sk->sk_state_change(sk);
|
|
||||||
+
|
|
||||||
+ /* TODO: how to send a FIN if we haven't done that? */
|
|
||||||
+ if (mode & SEND_SHUTDOWN)
|
|
||||||
+ ;
|
|
||||||
+
|
|
||||||
+ release_sock(sk);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void get_ringbuffer_rw_status(struct vmbus_channel *channel,
|
+static void get_ringbuffer_rw_status(struct vmbus_channel *channel,
|
||||||
+ bool *can_read, bool *can_write)
|
+ bool *can_read, bool *can_write)
|
||||||
+{
|
+{
|
||||||
@ -742,7 +731,7 @@ index 0000000..013d684
|
|||||||
+ hv_get_ringbuffer_availbytes(&channel->inbound,
|
+ hv_get_ringbuffer_availbytes(&channel->inbound,
|
||||||
+ &avl_read_bytes,
|
+ &avl_read_bytes,
|
||||||
+ &dummy);
|
+ &dummy);
|
||||||
+ /* 0-size payload meaans FIN */
|
+ /* 0-size payload means FIN */
|
||||||
+ *can_read = avl_read_bytes >= HVSOCK_PKT_LEN(0);
|
+ *can_read = avl_read_bytes >= HVSOCK_PKT_LEN(0);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@ -765,14 +754,86 @@ index 0000000..013d684
|
|||||||
+ &dummy,
|
+ &dummy,
|
||||||
+ &avl_write_bytes);
|
+ &avl_write_bytes);
|
||||||
+
|
+
|
||||||
+ if (avl_write_bytes < HVSOCK_PKT_LEN(1))
|
+ if (avl_write_bytes < HVSOCK_PKT_LEN(1) + HVSOCK_PKT_LEN(0))
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+
|
+
|
||||||
+ /* The ringbuffer can't be 100% full */
|
+ /* The ringbuffer mustn't be 100% full, and we should reserve a
|
||||||
+ ret = avl_write_bytes - HVSOCK_PKT_LEN(1);
|
+ * zero-length-payload packet for the FIN: see hv_ringbuffer_write()
|
||||||
|
+ * and hvsock_shutdown().
|
||||||
|
+ */
|
||||||
|
+ ret = avl_write_bytes - HVSOCK_PKT_LEN(1) - HVSOCK_PKT_LEN(0);
|
||||||
|
+
|
||||||
+ return round_down(ret, 8);
|
+ return round_down(ret, 8);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
|
+static int hvsock_send_data(struct vmbus_channel *channel,
|
||||||
|
+ struct hvsock_sock *hvsk,
|
||||||
|
+ size_t to_write)
|
||||||
|
+{
|
||||||
|
+ hvsk->send->hdr.pkt_type = 1;
|
||||||
|
+ hvsk->send->hdr.data_size = to_write;
|
||||||
|
+ return vmbus_sendpacket(channel, &hvsk->send->hdr,
|
||||||
|
+ sizeof(hvsk->send->hdr) + to_write,
|
||||||
|
+ 0, VM_PKT_DATA_INBAND, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int hvsock_recv_data(struct vmbus_channel *channel,
|
||||||
|
+ struct hvsock_sock *hvsk,
|
||||||
|
+ size_t *payload_len)
|
||||||
|
+{
|
||||||
|
+ u32 buffer_actual_len;
|
||||||
|
+ u64 dummy_req_id;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = vmbus_recvpacket(channel, &hvsk->recv->hdr,
|
||||||
|
+ sizeof(hvsk->recv->hdr) +
|
||||||
|
+ sizeof(hvsk->recv->buf),
|
||||||
|
+ &buffer_actual_len, &dummy_req_id);
|
||||||
|
+ if (ret != 0 || buffer_actual_len <= sizeof(hvsk->recv->hdr))
|
||||||
|
+ *payload_len = 0;
|
||||||
|
+ else
|
||||||
|
+ *payload_len = hvsk->recv->hdr.data_size;
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int hvsock_shutdown(struct socket *sock, int mode)
|
||||||
|
+{
|
||||||
|
+ struct hvsock_sock *hvsk;
|
||||||
|
+ struct sock *sk;
|
||||||
|
+
|
||||||
|
+ if (mode < SHUT_RD || mode > SHUT_RDWR)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ /* This maps:
|
||||||
|
+ * SHUT_RD (0) -> RCV_SHUTDOWN (1)
|
||||||
|
+ * SHUT_WR (1) -> SEND_SHUTDOWN (2)
|
||||||
|
+ * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
|
||||||
|
+ */
|
||||||
|
+ ++mode;
|
||||||
|
+
|
||||||
|
+ if (sock->state != SS_CONNECTED)
|
||||||
|
+ return -ENOTCONN;
|
||||||
|
+
|
||||||
|
+ sock->state = SS_DISCONNECTING;
|
||||||
|
+
|
||||||
|
+ sk = sock->sk;
|
||||||
|
+
|
||||||
|
+ lock_sock(sk);
|
||||||
|
+
|
||||||
|
+ sk->sk_shutdown |= mode;
|
||||||
|
+ sk->sk_state_change(sk);
|
||||||
|
+
|
||||||
|
+ if (mode & SEND_SHUTDOWN) {
|
||||||
|
+ hvsk = sk_to_hvsock(sk);
|
||||||
|
+ /* It can't fail: see get_ringbuffer_writable_bytes(). */
|
||||||
|
+ (void)hvsock_send_data(hvsk->channel, hvsk, 0);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ release_sock(sk);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
+static unsigned int hvsock_poll(struct file *file, struct socket *sock,
|
+static unsigned int hvsock_poll(struct file *file, struct socket *sock,
|
||||||
+ poll_table *wait)
|
+ poll_table *wait)
|
||||||
+{
|
+{
|
||||||
@ -898,7 +959,6 @@ index 0000000..013d684
|
|||||||
+ if (!sk)
|
+ if (!sk)
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+
|
+
|
||||||
+ sk->sk_socket->state = SS_UNCONNECTED;
|
|
||||||
+ sk->sk_state = SS_UNCONNECTED;
|
+ sk->sk_state = SS_UNCONNECTED;
|
||||||
+ sock_set_flag(sk, SOCK_DONE);
|
+ sock_set_flag(sk, SOCK_DONE);
|
||||||
+
|
+
|
||||||
@ -932,7 +992,7 @@ index 0000000..013d684
|
|||||||
+ sk = hvsock_find_bound_socket(&hv_addr);
|
+ sk = hvsock_find_bound_socket(&hv_addr);
|
||||||
+
|
+
|
||||||
+ if (!sk || (conn_from_host && sk->sk_state != SS_LISTEN) ||
|
+ if (!sk || (conn_from_host && sk->sk_state != SS_LISTEN) ||
|
||||||
+ (!conn_from_host && sk->sk_state != SS_CONNECTING)) {
|
+ (!conn_from_host && sk->sk_state != SS_CONNECTING)) {
|
||||||
+ ret = -ENXIO;
|
+ ret = -ENXIO;
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+ }
|
+ }
|
||||||
@ -943,12 +1003,11 @@ index 0000000..013d684
|
|||||||
+ goto out;
|
+ goto out;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ new_sk = __hvsock_create(sock_net(sk), NULL, GFP_KERNEL,
|
+ ret = hvsock_create(sock_net(sk), NULL, GFP_KERNEL,
|
||||||
+ sk->sk_type);
|
+ sk->sk_type, &new_sk);
|
||||||
+ if (!new_sk) {
|
+ if (ret != 0)
|
||||||
+ ret = -ENOMEM;
|
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+ }
|
+
|
||||||
+ new_sk->sk_state = SS_CONNECTING;
|
+ new_sk->sk_state = SS_CONNECTING;
|
||||||
+ new_hvsk = sk_to_hvsock(new_sk);
|
+ new_hvsk = sk_to_hvsock(new_sk);
|
||||||
+ new_hvsk->channel = channel;
|
+ new_hvsk->channel = channel;
|
||||||
@ -960,9 +1019,8 @@ index 0000000..013d684
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ set_channel_read_state(channel, false);
|
+ set_channel_read_state(channel, false);
|
||||||
+ vmbus_set_chn_rescind_callback(channel, hvsock_close_connection);
|
+ ret = vmbus_open(channel, send_ring_page * PAGE_SIZE,
|
||||||
+ ret = vmbus_open(channel, VMBUS_RINGBUFFER_SIZE_HVSOCK_SND,
|
+ recv_ring_page * PAGE_SIZE, NULL, 0,
|
||||||
+ VMBUS_RINGBUFFER_SIZE_HVSOCK_RCV, NULL, 0,
|
|
||||||
+ hvsock_on_channel_cb, conn_from_host ? new_sk : sk);
|
+ hvsock_on_channel_cb, conn_from_host ? new_sk : sk);
|
||||||
+ if (ret != 0) {
|
+ if (ret != 0) {
|
||||||
+ if (conn_from_host) {
|
+ if (conn_from_host) {
|
||||||
@ -974,6 +1032,7 @@ index 0000000..013d684
|
|||||||
+ goto out;
|
+ goto out;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ vmbus_set_chn_rescind_callback(channel, hvsock_close_connection);
|
||||||
+ set_channel_pending_send_size(channel,
|
+ set_channel_pending_send_size(channel,
|
||||||
+ HVSOCK_PKT_LEN(HVSOCK_SND_THRESHOLD));
|
+ HVSOCK_PKT_LEN(HVSOCK_SND_THRESHOLD));
|
||||||
+
|
+
|
||||||
@ -1264,17 +1323,6 @@ index 0000000..013d684
|
|||||||
+ return ret;
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int hvsock_send_data(struct vmbus_channel *channel,
|
|
||||||
+ struct hvsock_sock *hvsk,
|
|
||||||
+ size_t to_write)
|
|
||||||
+{
|
|
||||||
+ hvsk->send->hdr.pkt_type = 1;
|
|
||||||
+ hvsk->send->hdr.data_size = to_write;
|
|
||||||
+ return vmbus_sendpacket(channel, &hvsk->send->hdr,
|
|
||||||
+ sizeof(hvsk->send->hdr) + to_write,
|
|
||||||
+ 0, VM_PKT_DATA_INBAND, 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static
|
+static
|
||||||
+int hvsock_sendmsg_wait(struct sock *sk, struct msghdr *msg, size_t len)
|
+int hvsock_sendmsg_wait(struct sock *sk, struct msghdr *msg, size_t len)
|
||||||
+{
|
+{
|
||||||
@ -1432,26 +1480,6 @@ index 0000000..013d684
|
|||||||
+ return ret;
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int hvsock_recv_data(struct vmbus_channel *channel,
|
|
||||||
+ struct hvsock_sock *hvsk,
|
|
||||||
+ size_t *payload_len)
|
|
||||||
+{
|
|
||||||
+ u32 buffer_actual_len;
|
|
||||||
+ u64 dummy_req_id;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = vmbus_recvpacket(channel, &hvsk->recv->hdr,
|
|
||||||
+ sizeof(hvsk->recv->hdr) +
|
|
||||||
+ sizeof(hvsk->recv->buf),
|
|
||||||
+ &buffer_actual_len, &dummy_req_id);
|
|
||||||
+ if (ret != 0 || buffer_actual_len <= sizeof(hvsk->recv->hdr))
|
|
||||||
+ *payload_len = 0;
|
|
||||||
+ else
|
|
||||||
+ *payload_len = hvsk->recv->hdr.data_size;
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int hvsock_recvmsg_wait(struct sock *sk, struct msghdr *msg,
|
+static int hvsock_recvmsg_wait(struct sock *sk, struct msghdr *msg,
|
||||||
+ size_t len, int flags)
|
+ size_t len, int flags)
|
||||||
+{
|
+{
|
||||||
@ -1651,9 +1679,11 @@ index 0000000..013d684
|
|||||||
+ .sendpage = sock_no_sendpage,
|
+ .sendpage = sock_no_sendpage,
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+static int hvsock_create(struct net *net, struct socket *sock,
|
+static int hvsock_create_sock(struct net *net, struct socket *sock,
|
||||||
+ int protocol, int kern)
|
+ int protocol, int kern)
|
||||||
+{
|
+{
|
||||||
|
+ struct sock *sk;
|
||||||
|
+
|
||||||
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
|
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
|
||||||
+ return -EPERM;
|
+ return -EPERM;
|
||||||
+
|
+
|
||||||
@ -1670,12 +1700,12 @@ index 0000000..013d684
|
|||||||
+
|
+
|
||||||
+ sock->state = SS_UNCONNECTED;
|
+ sock->state = SS_UNCONNECTED;
|
||||||
+
|
+
|
||||||
+ return __hvsock_create(net, sock, GFP_KERNEL, 0) ? 0 : -ENOMEM;
|
+ return hvsock_create(net, sock, GFP_KERNEL, 0, &sk);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static const struct net_proto_family hvsock_family_ops = {
|
+static const struct net_proto_family hvsock_family_ops = {
|
||||||
+ .family = AF_HYPERV,
|
+ .family = AF_HYPERV,
|
||||||
+ .create = hvsock_create,
|
+ .create = hvsock_create_sock,
|
||||||
+ .owner = THIS_MODULE,
|
+ .owner = THIS_MODULE,
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
@ -1719,6 +1749,12 @@ index 0000000..013d684
|
|||||||
+{
|
+{
|
||||||
+ int ret;
|
+ int ret;
|
||||||
+
|
+
|
||||||
|
+ if (send_ring_page < DEF_RINGBUFFER_PAGES_HVSOCK_SND)
|
||||||
|
+ send_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_SND;
|
||||||
|
+
|
||||||
|
+ if (recv_ring_page < DEF_RINGBUFFER_PAGES_HVSOCK_RCV)
|
||||||
|
+ recv_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_RCV;
|
||||||
|
+
|
||||||
+ /* Hyper-V Sockets requires at least VMBus 4.0 */
|
+ /* Hyper-V Sockets requires at least VMBus 4.0 */
|
||||||
+ if ((vmbus_proto_version >> 16) < 4) {
|
+ if ((vmbus_proto_version >> 16) < 4) {
|
||||||
+ pr_err("failed to load: VMBus 4 or later is required\n");
|
+ pr_err("failed to load: VMBus 4 or later is required\n");
|
@ -1,7 +1,7 @@
|
|||||||
From 2cffe53eda5ea0b90968867317149b57eb6d5b13 Mon Sep 17 00:00:00 2001
|
From 7034fda17f5619f598de93fecdfd0af6a96b18f4 Mon Sep 17 00:00:00 2001
|
||||||
From: Dexuan Cui <decui@microsoft.com>
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
Date: Mon, 21 Mar 2016 02:53:08 -0700
|
Date: Mon, 21 Mar 2016 02:53:08 -0700
|
||||||
Subject: [PATCH 26/28] net: add the AF_HYPERV entries to family name tables
|
Subject: [PATCH 38/40] net: add the AF_HYPERV entries to family name tables
|
||||||
|
|
||||||
This is for the hv_sock driver, which introduces AF_HYPERV(42).
|
This is for the hv_sock driver, which introduces AF_HYPERV(42).
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 6d6ad94bf42ceff0785f28382ba2c4a2cc6725d3 Mon Sep 17 00:00:00 2001
|
From 0eba2b0c75b7dddedeedd6c827d71d0f23ae00ac Mon Sep 17 00:00:00 2001
|
||||||
From: Ian Campbell <ian.campbell@docker.com>
|
From: Ian Campbell <ian.campbell@docker.com>
|
||||||
Date: Wed, 4 May 2016 14:21:53 +0100
|
Date: Wed, 4 May 2016 14:21:53 +0100
|
||||||
Subject: [PATCH 27/28] VSOCK: do not disconnect socket when peer has shutdown
|
Subject: [PATCH 39/40] VSOCK: do not disconnect socket when peer has shutdown
|
||||||
SEND only
|
SEND only
|
||||||
|
|
||||||
The peer may be expecting a reply having sent a request and then done a
|
The peer may be expecting a reply having sent a request and then done a
|
@ -0,0 +1,150 @@
|
|||||||
|
From 87cb6b00e44a0d496c623ea19801e2a9415a9759 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dexuan Cui <decui@microsoft.com>
|
||||||
|
Date: Mon, 16 May 2016 22:26:05 +0800
|
||||||
|
Subject: [PATCH 40/40] Drivers: hv: vmbus: fix the race when querying &
|
||||||
|
updating the percpu list
|
||||||
|
|
||||||
|
There is a rare race when we remove an entry from the global list
|
||||||
|
hv_context.percpu_list[cpu] in hv_process_channel_removal() ->
|
||||||
|
percpu_channel_deq() -> list_del(): at this time, if vmbus_on_event() ->
|
||||||
|
process_chn_event() -> pcpu_relid2channel() is trying to query the list,
|
||||||
|
we can get the general protection fault:
|
||||||
|
|
||||||
|
general protection fault: 0000 [#1] SMP
|
||||||
|
...
|
||||||
|
RIP: 0010:[<ffffffff81461b6b>] [<ffffffff81461b6b>] vmbus_on_event+0xc4/0x149
|
||||||
|
|
||||||
|
Similarly, we also have the issue in the code path: vmbus_process_offer() ->
|
||||||
|
percpu_channel_enq().
|
||||||
|
|
||||||
|
We can resolve the issue by disabling the tasklet when updating the list.
|
||||||
|
|
||||||
|
Reported-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||||
|
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||||
|
Origin: https://github.com/dcui/linux/commit/cef5caca69a9104988a0e1c5185f919f7adbf1d2.patch
|
||||||
|
---
|
||||||
|
drivers/hv/channel.c | 3 +++
|
||||||
|
drivers/hv/channel_mgmt.c | 20 +++++++++-----------
|
||||||
|
include/linux/hyperv.h | 3 +++
|
||||||
|
3 files changed, 15 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||||
|
index 57a1b65..f66fb3c 100644
|
||||||
|
--- a/drivers/hv/channel.c
|
||||||
|
+++ b/drivers/hv/channel.c
|
||||||
|
@@ -546,8 +546,11 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||||
|
put_cpu();
|
||||||
|
smp_call_function_single(channel->target_cpu, reset_channel_cb,
|
||||||
|
channel, true);
|
||||||
|
+ smp_call_function_single(channel->target_cpu,
|
||||||
|
+ percpu_channel_deq, channel, true);
|
||||||
|
} else {
|
||||||
|
reset_channel_cb(channel);
|
||||||
|
+ percpu_channel_deq(channel);
|
||||||
|
put_cpu();
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||||
|
index c892db5..ac48fe9 100644
|
||||||
|
--- a/drivers/hv/channel_mgmt.c
|
||||||
|
+++ b/drivers/hv/channel_mgmt.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
@@ -277,7 +278,7 @@ static void free_channel(struct vmbus_channel *channel)
|
||||||
|
kfree(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void percpu_channel_enq(void *arg)
|
||||||
|
+void percpu_channel_enq(void *arg)
|
||||||
|
{
|
||||||
|
struct vmbus_channel *channel = arg;
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
@@ -285,7 +286,7 @@ static void percpu_channel_enq(void *arg)
|
||||||
|
list_add_tail(&channel->percpu_list, &hv_context.percpu_list[cpu]);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void percpu_channel_deq(void *arg)
|
||||||
|
+void percpu_channel_deq(void *arg)
|
||||||
|
{
|
||||||
|
struct vmbus_channel *channel = arg;
|
||||||
|
|
||||||
|
@@ -313,15 +314,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||||
|
BUG_ON(!channel->rescind);
|
||||||
|
BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
|
||||||
|
|
||||||
|
- if (channel->target_cpu != get_cpu()) {
|
||||||
|
- put_cpu();
|
||||||
|
- smp_call_function_single(channel->target_cpu,
|
||||||
|
- percpu_channel_deq, channel, true);
|
||||||
|
- } else {
|
||||||
|
- percpu_channel_deq(channel);
|
||||||
|
- put_cpu();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (channel->primary_channel == NULL) {
|
||||||
|
list_del(&channel->listentry);
|
||||||
|
|
||||||
|
@@ -363,6 +355,7 @@ void vmbus_free_channels(void)
|
||||||
|
*/
|
||||||
|
static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
{
|
||||||
|
+ struct tasklet_struct *tasklet;
|
||||||
|
struct vmbus_channel *channel;
|
||||||
|
bool fnew = true;
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -409,6 +402,8 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
|
||||||
|
init_vp_index(newchannel, dev_type);
|
||||||
|
|
||||||
|
+ tasklet = hv_context.event_dpc[newchannel->target_cpu];
|
||||||
|
+ tasklet_disable(tasklet);
|
||||||
|
if (newchannel->target_cpu != get_cpu()) {
|
||||||
|
put_cpu();
|
||||||
|
smp_call_function_single(newchannel->target_cpu,
|
||||||
|
@@ -418,6 +413,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||||
|
percpu_channel_enq(newchannel);
|
||||||
|
put_cpu();
|
||||||
|
}
|
||||||
|
+ tasklet_enable(tasklet);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This state is used to indicate a successful open
|
||||||
|
@@ -469,6 +465,7 @@ err_deq_chan:
|
||||||
|
list_del(&newchannel->listentry);
|
||||||
|
mutex_unlock(&vmbus_connection.channel_mutex);
|
||||||
|
|
||||||
|
+ tasklet_disable(tasklet);
|
||||||
|
if (newchannel->target_cpu != get_cpu()) {
|
||||||
|
put_cpu();
|
||||||
|
smp_call_function_single(newchannel->target_cpu,
|
||||||
|
@@ -477,6 +474,7 @@ err_deq_chan:
|
||||||
|
percpu_channel_deq(newchannel);
|
||||||
|
put_cpu();
|
||||||
|
}
|
||||||
|
+ tasklet_enable(tasklet);
|
||||||
|
|
||||||
|
err_free_chan:
|
||||||
|
free_channel(newchannel);
|
||||||
|
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||||
|
index 187d4bd..a69364b 100644
|
||||||
|
--- a/include/linux/hyperv.h
|
||||||
|
+++ b/include/linux/hyperv.h
|
||||||
|
@@ -1339,6 +1339,9 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
|
||||||
|
struct icmsg_negotiate *, u8 *, int,
|
||||||
|
int);
|
||||||
|
|
||||||
|
+void percpu_channel_enq(void *arg);
|
||||||
|
+void percpu_channel_deq(void *arg);
|
||||||
|
+
|
||||||
|
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
2.8.2
|
||||||
|
|
Loading…
Reference in New Issue
Block a user