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:
Rolf Neugebauer 2016-05-16 23:45:10 +01:00
parent 04d5a39638
commit 61b38236a9
41 changed files with 1893 additions and 231 deletions

View File

@ -1,7 +1,7 @@
From 31adb74f5668e7e44615a2854742f8726a818533 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
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:

View File

@ -1,7 +1,7 @@
From 4b274b13e7dfe4ac54072f324738c487a36b78b8 Mon Sep 17 00:00:00 2001
From: Julia Lawall <julia.lawall@lip6.fr>
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
them as const.

View File

@ -1,7 +1,7 @@
From 31fb7962193b46e8f7e24ac350e3efc486f0fd90 Mon Sep 17 00:00:00 2001
From: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
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
is not allowed until either the wait has taken place or finish_wait has

View File

@ -1,7 +1,7 @@
From 891b9c6111fc77750b261cc03f8ac7a80441701a Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
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
core code. The transport may want its own transport-specific function

View File

@ -1,7 +1,7 @@
From a27fee87d915bfb9edf720f9068c3aed6649aa0c Mon Sep 17 00:00:00 2001
From: Asias He <asias@redhat.com>
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
virtio_transporto and vhost_vsock kernel modules.

View File

@ -1,7 +1,7 @@
From 19cfdea4fa3fa9136c234ac695f628fce73b40c2 Mon Sep 17 00:00:00 2001
From: Asias He <asias@redhat.com>
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
guest.

View File

@ -1,7 +1,7 @@
From fd467c3335938b8eca0489008c390ad16a01aee7 Mon Sep 17 00:00:00 2001
From: Asias He <asias@redhat.com>
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
host.

View File

@ -1,7 +1,7 @@
From 5d2849bde15e969b8cf1eb2f5e818b62ec2181ec Mon Sep 17 00:00:00 2001
From: Asias He <asias@redhat.com>
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.

View File

@ -1,7 +1,7 @@
From 81b78a051aa8c61743abcc266eb9c7511dd19a62 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell@docker.com>
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.
The VSOCK addressing schema does not really lend itself to simply creating an

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>
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()
process_chn_event(), running in the tasklet, can race with

View File

@ -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>
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()
This fixes an incorrect assumption of channel state in the function.

View File

@ -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>
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
In the path vmbus_onoffer_rescind() -> vmbus_device_unregister() ->
@ -55,7 +55,7 @@ index b3c14ca..2889d97 100644
tasklet_enable(tasklet);
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
+++ b/drivers/hv/channel_mgmt.c
@@ -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);
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
+++ b/drivers/hv/vmbus_drv.c
@@ -602,23 +602,11 @@ static int vmbus_remove(struct device *child_device)

View File

@ -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>
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()
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(-)
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
+++ b/drivers/hv/channel_mgmt.c
@@ -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);
list_del(&newchannel->listentry);
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);
if (channel == NULL) {

View File

@ -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>
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
spinlock is unnecessary here.
@ -18,7 +18,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
3 files changed, 10 insertions(+), 11 deletions(-)
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
+++ b/drivers/hv/channel_mgmt.c
@@ -206,9 +206,9 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>
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
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(+)
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
+++ 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;
}

View File

@ -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>
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)
A helper function is also added.
@ -15,7 +15,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 file changed, 7 insertions(+)
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
+++ b/include/linux/hyperv.h
@@ -237,6 +237,7 @@ struct vmbus_channel_offer {
@ -26,7 +26,7 @@ index fda6310..9fb2130 100644
struct vmpacket_descriptor {
u16 type;
@@ -771,6 +772,12 @@ struct vmbus_channel {
@@ -797,6 +798,12 @@ struct vmbus_channel {
enum hv_signal_policy signal_policy;
};

View File

@ -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>
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
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(-)
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
+++ b/drivers/hv/channel.c
@@ -659,6 +659,9 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,

View File

@ -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>
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
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(+)
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
+++ b/drivers/hv/channel.c
@@ -219,6 +219,21 @@ error0:
@ -46,10 +46,10 @@ index a7f9e3e..239b072 100644
* create_gpadl_header - Creates a gpadl for the specified buffer
*/
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
+++ 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_UNLOAD, 0, NULL},
{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
index 9fb2130..3f485a4 100644
index a4f105d..191bc5d 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -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_message_header header;
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;

View File

@ -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>
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
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(+)
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
+++ 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_device *hv_dev = device_to_hv_device(device);
@ -31,14 +31,14 @@ index 7e46a48..7d607ad 100644
+ if (is_hvsock_channel(hv_dev->channel))
+ 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;
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
+++ 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 {
const char *name;

View File

@ -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

View File

@ -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>
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.
@ -15,10 +15,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2 files changed, 20 insertions(+)
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
+++ 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);
if (channel->device_obj) {
@ -29,7 +29,7 @@ index 4d61f41..421e3dd 100644
/*
* We will have to unregister this device from the
* 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;
}
EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present);
@ -41,10 +41,10 @@ index 4d61f41..421e3dd 100644
+}
+EXPORT_SYMBOL_GPL(vmbus_set_chn_rescind_callback);
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
+++ 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);
/*
@ -57,7 +57,7 @@ index 9ee79af..09e9ec1 100644
* The spinlock to protect the structure. It is being used to protect
* test-and-set access to various attributes of the structure as well
* 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 (*sc_cr_cb)(struct vmbus_channel *new_sc));

View File

@ -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>
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()
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(-)
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
+++ 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);
BUG_ON(!channel->rescind);
@ -29,7 +29,7 @@ index 421e3dd..0fe9665 100644
if (channel->target_cpu != get_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) {
@ -39,15 +39,15 @@ index 421e3dd..0fe9665 100644
primary_channel = channel;
} else {
@@ -251,6 +250,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
struct vmbus_channel *channel;
@@ -367,6 +366,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
bool fnew = true;
unsigned long flags;
u16 dev_type;
+ int ret;
/* Make sure this is a new offer */
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()
* method.
*/
@ -60,7 +60,7 @@ index 421e3dd..0fe9665 100644
pr_err("unable to add child device object (relid %d)\n",
newchannel->offermsg.child_relid);
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;
rescind = (struct vmbus_channel_rescind_offer *)hdr;
@ -69,7 +69,7 @@ index 421e3dd..0fe9665 100644
channel = relid2channel(rescind->child_relid);
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_release_relid() on error.
*/
@ -78,7 +78,7 @@ index 421e3dd..0fe9665 100644
}
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->chn_rescind_callback) {
channel->chn_rescind_callback(channel);
@ -87,7 +87,7 @@ index 421e3dd..0fe9665 100644
}
/*
* 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,
channel->offermsg.child_relid);
}
@ -136,10 +136,10 @@ index 521f48e..09c08b5 100644
return found_channel;
}
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
+++ 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);
void vmbus_driver_unregister(struct hv_driver *hv_driver);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>
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.

View File

@ -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>
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
b7ac4eb(kcm: Kernel Connection Multiplexor module).

View File

@ -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>
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
communicate with service providing remote processors.

View File

@ -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>
Date: Wed, 11 May 2016 10:52:37 -0700
Subject: [PATCH 25/28] hv_sock: introduce Hyper-V Sockets
Date: Sun, 15 May 2016 09:53:11 -0700
Subject: [PATCH 37/40] hv_sock: introduce Hyper-V Sockets
Hyper-V Sockets (hv_sock) supplies a byte-stream based communication
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: Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: Cathy Avery <cavery@redhat.com>
Origin: http://patchwork.ozlabs.org/patch/621190/
Origin: https://patchwork.ozlabs.org/patch/622404/
---
MAINTAINERS | 2 +
include/linux/hyperv.h | 14 +
@ -33,8 +33,8 @@ Origin: http://patchwork.ozlabs.org/patch/621190/
net/Makefile | 1 +
net/hv_sock/Kconfig | 10 +
net/hv_sock/Makefile | 3 +
net/hv_sock/af_hvsock.c | 1484 +++++++++++++++++++++++++++++++++++++++++++
10 files changed, 1621 insertions(+), 1 deletion(-)
net/hv_sock/af_hvsock.c | 1520 +++++++++++++++++++++++++++++++++++++++++++
10 files changed, 1657 insertions(+), 1 deletion(-)
create mode 100644 include/net/af_hvsock.h
create mode 100644 net/hv_sock/Kconfig
create mode 100644 net/hv_sock/Makefile
@ -55,10 +55,10 @@ index 9a70d2d..1021706 100644
F: Documentation/ABI/stable/sysfs-bus-vmbus
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
+++ 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,
const uuid_le *shv_host_servie_id);
@ -102,7 +102,7 @@ index dbd81e7..6634c47 100644
/* Maximum queue length specifiable by listen. */
diff --git a/include/net/af_hvsock.h b/include/net/af_hvsock.h
new file mode 100644
index 0000000..e002397
index 0000000..7c8c41e
--- /dev/null
+++ b/include/net/af_hvsock.h
@@ -0,0 +1,78 @@
@ -113,7 +113,7 @@ index 0000000..e002397
+#include <linux/hyperv.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:
+ * see hv_ringbuffer_init();
@ -123,18 +123,18 @@ index 0000000..e002397
+ * need at least 2 extra pages for ringbuffer data.
+ */
+#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
+ * 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
+ * read/write index etc, rather than data), we only have 1 page for 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
+ * the minimal size by default, because the 1st page of the two is used as the
+ * shared read/write index etc, rather than data), we only have 1 page for
+ * ringbuffer data, this means: the max payload length for hvsock data is
+ * 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().
+ */
+#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
+ * value must be less than HVSOCK_SND_BUF_SZ.
@ -276,10 +276,10 @@ index 0000000..716c012
+hv_sock-y += af_hvsock.o
diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c
new file mode 100644
index 0000000..013d684
index 0000000..b91bd60
--- /dev/null
+++ 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 host and the virtual machines running on it.
@ -317,6 +317,21 @@ index 0000000..013d684
+#include <linux/module.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 = {
+ .name = "HV_SOCK",
+ .owner = THIS_MODULE,
@ -525,6 +540,7 @@ index 0000000..013d684
+
+ kfree(hvsk->send);
+ kfree(hvsk->recv);
+ atomic_dec(&total_num_hvsock);
+
+ if (!channel)
+ return;
@ -581,43 +597,48 @@ index 0000000..013d684
+ return 0;
+}
+
+static struct sock *__hvsock_create(struct net *net, struct socket *sock,
+ gfp_t priority, unsigned short type)
+static int hvsock_create(struct net *net, struct socket *sock,
+ gfp_t priority, unsigned short type,
+ struct sock **sk)
+{
+ struct hvsock_send_buf *send = NULL;
+ struct hvsock_recv_buf *recv = NULL;
+
+ struct hvsock_sock *hvsk;
+ struct sock *sk;
+ int ret = -EMFILE;
+ int num_hvsock;
+
+ send = kmalloc(sizeof(struct hvsock_send_buf), GFP_KERNEL);
+ recv = kmalloc(sizeof(struct hvsock_recv_buf), GFP_KERNEL);
+ num_hvsock = atomic_inc_return(&total_num_hvsock);
+ 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)
+ goto err;
+
+ sk = sk_alloc(net, AF_HYPERV, priority, &hvsock_proto, 0);
+ if (!sk)
+ *sk = sk_alloc(net, AF_HYPERV, priority, &hvsock_proto, 0);
+ if (!*sk)
+ 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
+ * non-NULL. We make sure that our sockets always have a type by
+ /* (*sk)->sk_type is normally set in sock_init_data, but only if sock
+ * is non-NULL. We make sure that our sockets always have a type by
+ * setting it here if needed.
+ */
+ 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. */
+ sk->sk_backlog_rcv = NULL;
+ (*sk)->sk_backlog_rcv = NULL;
+
+ sk->sk_state = 0;
+ sock_reset_flag(sk, SOCK_DONE);
+ (*sk)->sk_state = 0;
+ sock_reset_flag(*sk, SOCK_DONE);
+
+ hvsk = sk_to_hvsock(sk);
+ hvsk = sk_to_hvsock(*sk);
+
+ hvsk->send = send;
+ hvsk->recv = recv;
@ -636,11 +657,13 @@ index 0000000..013d684
+ hvsk->recv->data_len = 0;
+ hvsk->recv->data_offset = 0;
+
+ return sk;
+ return 0;
+err:
+ atomic_dec(&total_num_hvsock);
+ kfree(send);
+ kfree(recv);
+ return NULL;
+ *sk = NULL;
+ return ret;
+}
+
+static int hvsock_bind(struct socket *sock, struct sockaddr *addr,
@ -699,40 +722,6 @@ index 0000000..013d684
+ 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,
+ bool *can_read, bool *can_write)
+{
@ -742,7 +731,7 @@ index 0000000..013d684
+ hv_get_ringbuffer_availbytes(&channel->inbound,
+ &avl_read_bytes,
+ &dummy);
+ /* 0-size payload meaans FIN */
+ /* 0-size payload means FIN */
+ *can_read = avl_read_bytes >= HVSOCK_PKT_LEN(0);
+ }
+
@ -765,14 +754,86 @@ index 0000000..013d684
+ &dummy,
+ &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;
+
+ /* The ringbuffer can't be 100% full */
+ ret = avl_write_bytes - HVSOCK_PKT_LEN(1);
+ /* The ringbuffer mustn't be 100% full, and we should reserve a
+ * 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);
+}
+
+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,
+ poll_table *wait)
+{
@ -898,7 +959,6 @@ index 0000000..013d684
+ if (!sk)
+ goto out;
+
+ sk->sk_socket->state = SS_UNCONNECTED;
+ sk->sk_state = SS_UNCONNECTED;
+ sock_set_flag(sk, SOCK_DONE);
+
@ -943,12 +1003,11 @@ index 0000000..013d684
+ goto out;
+ }
+
+ new_sk = __hvsock_create(sock_net(sk), NULL, GFP_KERNEL,
+ sk->sk_type);
+ if (!new_sk) {
+ ret = -ENOMEM;
+ ret = hvsock_create(sock_net(sk), NULL, GFP_KERNEL,
+ sk->sk_type, &new_sk);
+ if (ret != 0)
+ goto out;
+ }
+
+ new_sk->sk_state = SS_CONNECTING;
+ new_hvsk = sk_to_hvsock(new_sk);
+ new_hvsk->channel = channel;
@ -960,9 +1019,8 @@ index 0000000..013d684
+ }
+
+ set_channel_read_state(channel, false);
+ vmbus_set_chn_rescind_callback(channel, hvsock_close_connection);
+ ret = vmbus_open(channel, VMBUS_RINGBUFFER_SIZE_HVSOCK_SND,
+ VMBUS_RINGBUFFER_SIZE_HVSOCK_RCV, NULL, 0,
+ ret = vmbus_open(channel, send_ring_page * PAGE_SIZE,
+ recv_ring_page * PAGE_SIZE, NULL, 0,
+ hvsock_on_channel_cb, conn_from_host ? new_sk : sk);
+ if (ret != 0) {
+ if (conn_from_host) {
@ -974,6 +1032,7 @@ index 0000000..013d684
+ goto out;
+ }
+
+ vmbus_set_chn_rescind_callback(channel, hvsock_close_connection);
+ set_channel_pending_send_size(channel,
+ HVSOCK_PKT_LEN(HVSOCK_SND_THRESHOLD));
+
@ -1264,17 +1323,6 @@ index 0000000..013d684
+ 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
+int hvsock_sendmsg_wait(struct sock *sk, struct msghdr *msg, size_t len)
+{
@ -1432,26 +1480,6 @@ index 0000000..013d684
+ 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,
+ size_t len, int flags)
+{
@ -1651,9 +1679,11 @@ index 0000000..013d684
+ .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)
+{
+ struct sock *sk;
+
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
@ -1670,12 +1700,12 @@ index 0000000..013d684
+
+ 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 = {
+ .family = AF_HYPERV,
+ .create = hvsock_create,
+ .create = hvsock_create_sock,
+ .owner = THIS_MODULE,
+};
+
@ -1719,6 +1749,12 @@ index 0000000..013d684
+{
+ 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 */
+ if ((vmbus_proto_version >> 16) < 4) {
+ pr_err("failed to load: VMBus 4 or later is required\n");

View File

@ -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>
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).

View File

@ -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>
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
The peer may be expecting a reply having sent a request and then done a

View File

@ -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