diff --git a/alpine/kernel/patches-4.9/0001-VSOCK-Only-allow-host-network-namespace-to-use-AF_VS.patch b/alpine/kernel/patches-4.9/0001-VSOCK-Only-allow-host-network-namespace-to-use-AF_VS.patch index 953ccaffe..3580b7d72 100644 --- a/alpine/kernel/patches-4.9/0001-VSOCK-Only-allow-host-network-namespace-to-use-AF_VS.patch +++ b/alpine/kernel/patches-4.9/0001-VSOCK-Only-allow-host-network-namespace-to-use-AF_VS.patch @@ -1,7 +1,7 @@ -From 1fc22bc5c2e3544786420355405038e4a12ffd72 Mon Sep 17 00:00:00 2001 +From fb4ee21f744b2639a1a7d495a732198a3e9c96ec Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 4 Apr 2016 14:50:10 +0100 -Subject: [PATCH 01/11] VSOCK: Only allow host network namespace to use +Subject: [PATCH 01/12] VSOCK: Only allow host network namespace to use AF_VSOCK. The VSOCK addressing schema does not really lend itself to simply creating an diff --git a/alpine/kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch b/alpine/kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch index 546eb742a..f6927a15b 100644 --- a/alpine/kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch +++ b/alpine/kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch @@ -1,7 +1,7 @@ -From 0d9748d2d26216421225b41643c6167fda91c26f Mon Sep 17 00:00:00 2001 +From 6d42aeb54b6231920d58ea324e67d94ffc01a11a Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Sat, 23 Jul 2016 01:35:51 +0000 -Subject: [PATCH 02/11] hv_sock: introduce Hyper-V Sockets +Subject: [PATCH 02/12] 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 diff --git a/alpine/kernel/patches-4.9/0003-vmbus-Don-t-spam-the-logs-with-unknown-GUIDs.patch b/alpine/kernel/patches-4.9/0003-vmbus-Don-t-spam-the-logs-with-unknown-GUIDs.patch index 01bdc41bf..22d4d25ee 100644 --- a/alpine/kernel/patches-4.9/0003-vmbus-Don-t-spam-the-logs-with-unknown-GUIDs.patch +++ b/alpine/kernel/patches-4.9/0003-vmbus-Don-t-spam-the-logs-with-unknown-GUIDs.patch @@ -1,7 +1,7 @@ -From c9168a8ff6c84924df9efec05257f74ed93981b2 Mon Sep 17 00:00:00 2001 +From 087c906e5cd36f32e8d0edcbea8a4cfb5bb98947 Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Mon, 23 May 2016 18:55:45 +0100 -Subject: [PATCH 03/11] vmbus: Don't spam the logs with unknown GUIDs +Subject: [PATCH 03/12] vmbus: Don't spam the logs with unknown GUIDs With Hyper-V sockets device types are introduced on the fly. The pr_info() then prints a message on every connection, which is way too verbose. Since diff --git a/alpine/kernel/patches-4.9/0004-Drivers-hv-utils-Fix-the-mapping-between-host-versio.patch b/alpine/kernel/patches-4.9/0004-Drivers-hv-utils-Fix-the-mapping-between-host-versio.patch index c8c274f5f..61c75bf2b 100644 --- a/alpine/kernel/patches-4.9/0004-Drivers-hv-utils-Fix-the-mapping-between-host-versio.patch +++ b/alpine/kernel/patches-4.9/0004-Drivers-hv-utils-Fix-the-mapping-between-host-versio.patch @@ -1,7 +1,7 @@ -From 24a17904f276ced95d717fc427c4f6ff256ac0a8 Mon Sep 17 00:00:00 2001 +From 59043b28040811e2af89841dbb4d3b9445ae67e1 Mon Sep 17 00:00:00 2001 From: Alex Ng Date: Sun, 6 Nov 2016 13:14:07 -0800 -Subject: [PATCH 04/11] Drivers: hv: utils: Fix the mapping between host +Subject: [PATCH 04/12] Drivers: hv: utils: Fix the mapping between host version and protocol to use We should intentionally declare the protocols to use for every known host diff --git a/alpine/kernel/patches-4.9/0005-Drivers-hv-utils-Force-TimeSync-version-3.0-on-Windo.patch b/alpine/kernel/patches-4.9/0005-Drivers-hv-utils-Force-TimeSync-version-3.0-on-Windo.patch deleted file mode 100644 index 2a1714cfb..000000000 --- a/alpine/kernel/patches-4.9/0005-Drivers-hv-utils-Force-TimeSync-version-3.0-on-Windo.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 5d339781f71a37083d4c4d304ba45b89aede184f Mon Sep 17 00:00:00 2001 -From: Rolf Neugebauer -Date: Wed, 11 Jan 2017 22:40:38 +0000 -Subject: [PATCH 05/11] Drivers: hv: utils: Force TimeSync version 3.0 on - Windows 10 - -Some older Windows 10 builds, including 10586 do not seem to -support TimeSync protocol 4.0 causing loss of time synchronisation -and a lot of log spam. - -Signed-off-by: Rolf Neugebauer ---- - drivers/hv/hv_util.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c -index e7707747f56d..5961f1a49deb 100644 ---- a/drivers/hv/hv_util.c -+++ b/drivers/hv/hv_util.c -@@ -401,7 +401,12 @@ static int util_probe(struct hv_device *dev, - default: - util_fw_version = UTIL_FW_VERSION; - sd_srv_version = SD_VERSION; -- ts_srv_version = TS_VERSION; -+ /* -+ * XXX rneugeba: force TimeSync Version to 3.0 on -+ * Windows 10 as well as older Windows 10 builds, -+ * including 10586 to not support version 4.0 -+ */ -+ ts_srv_version = TS_VERSION_3; - hb_srv_version = HB_VERSION; - } - --- -2.11.0 - diff --git a/alpine/kernel/patches-4.9/0007-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch b/alpine/kernel/patches-4.9/0005-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch similarity index 92% rename from alpine/kernel/patches-4.9/0007-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch rename to alpine/kernel/patches-4.9/0005-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch index 5bb3c56a6..6b80dcb9f 100644 --- a/alpine/kernel/patches-4.9/0007-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch +++ b/alpine/kernel/patches-4.9/0005-virtio-don-t-set-VIRTIO_NET_HDR_F_DATA_VALID-on-xmit.patch @@ -1,7 +1,7 @@ -From 00ef9fe4743da2cdd5b55d97335e678304329e24 Mon Sep 17 00:00:00 2001 +From ff8f8f00ebc17ee2cabc316ad610188db1e8fe5d Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Tue, 17 Jan 2017 18:13:51 +0000 -Subject: [PATCH 07/11] virtio: don't set VIRTIO_NET_HDR_F_DATA_VALID on xmit +Subject: [PATCH 05/12] virtio: don't set VIRTIO_NET_HDR_F_DATA_VALID on xmit This patch part reverts fd2a0437dc33 and e858fae2b0b8 which introduced a subtle change in how the virtio_net flags are derived from the SKBs diff --git a/alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch b/alpine/kernel/patches-4.9/0006-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch similarity index 96% rename from alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch rename to alpine/kernel/patches-4.9/0006-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch index 600d54c02..18993b163 100644 --- a/alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch +++ b/alpine/kernel/patches-4.9/0006-Drivers-hv-vmbus-Base-host-signaling-strictly-on-the.patch @@ -1,7 +1,7 @@ -From 72c60164c3508d229686d64e624d1d2f47d01676 Mon Sep 17 00:00:00 2001 +From dedfc354773877960dcf6c8a926faa4a94803ec5 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 6 Nov 2016 13:14:16 -0800 -Subject: [PATCH 08/11] Drivers: hv: vmbus: Base host signaling strictly on the +Subject: [PATCH 06/12] Drivers: hv: vmbus: Base host signaling strictly on the ring state One of the factors that can result in the host concluding that a given diff --git a/alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch b/alpine/kernel/patches-4.9/0007-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch similarity index 98% rename from alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch rename to alpine/kernel/patches-4.9/0007-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch index 0cc11ec30..bf7e2ba7d 100644 --- a/alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch +++ b/alpine/kernel/patches-4.9/0007-Drivers-hv-vmbus-On-write-cleanup-the-logic-to-inter.patch @@ -1,7 +1,7 @@ -From f0472d013423117cae77e00089485f7d976138f2 Mon Sep 17 00:00:00 2001 +From 59b43ccde9636cdb874156a6f6e570414eb3d67b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 6 Nov 2016 13:14:17 -0800 -Subject: [PATCH 09/11] Drivers: hv: vmbus: On write cleanup the logic to +Subject: [PATCH 07/12] Drivers: hv: vmbus: On write cleanup the logic to interrupt the host Signal the host when we determine the host is to be signaled. diff --git a/alpine/kernel/patches-4.9/0010-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch b/alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch similarity index 95% rename from alpine/kernel/patches-4.9/0010-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch rename to alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch index bb1aad0f2..3aa03acec 100644 --- a/alpine/kernel/patches-4.9/0010-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch +++ b/alpine/kernel/patches-4.9/0008-Drivers-hv-vmbus-On-the-read-path-cleanup-the-logic-.patch @@ -1,7 +1,7 @@ -From 9e0ab3ccac70147f6e0e04cf0872d6f477ec6b68 Mon Sep 17 00:00:00 2001 +From d77258d2dded3a5601ccd54edb6f99e035dc7b20 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 6 Nov 2016 13:14:18 -0800 -Subject: [PATCH 10/11] Drivers: hv: vmbus: On the read path cleanup the logic +Subject: [PATCH 08/12] Drivers: hv: vmbus: On the read path cleanup the logic to interrupt the host Signal the host when we determine the host is to be signaled - @@ -12,6 +12,7 @@ poll the channel. Make the necessary adjustments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman +(cherry picked from commit 3372592a140db69fd63837e81f048ab4abf8111e) --- drivers/hv/channel.c | 11 ++--------- drivers/hv/hyperv_vmbus.h | 4 ++-- diff --git a/alpine/kernel/patches-4.9/0011-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch b/alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch similarity index 86% rename from alpine/kernel/patches-4.9/0011-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch rename to alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch index c4a17b371..bce4bc4a1 100644 --- a/alpine/kernel/patches-4.9/0011-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch +++ b/alpine/kernel/patches-4.9/0009-Drivers-hv-vmbus-finally-fix-hv_need_to_signal_on_re.patch @@ -1,7 +1,7 @@ -From c9dc13e8f77c09369dae49f265176999e3f327c8 Mon Sep 17 00:00:00 2001 +From 21d5ad16c820d2e949ca80881986db3d228d8a33 Mon Sep 17 00:00:00 2001 From: Dexuan Cui -Date: Mon, 16 Jan 2017 15:46:19 +0800 -Subject: [PATCH 11/11] Drivers: hv: vmbus: finally fix +Date: Tue, 24 Jan 2017 06:54:46 +0000 +Subject: [PATCH 09/12] Drivers: hv: vmbus: finally fix hv_need_to_signal_on_read() Commit a389fcfd2cb5 ("Drivers: hv: vmbus: Fix signaling logic in hv_need_to_signal_on_read()") @@ -26,13 +26,12 @@ Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: - -Origin: Email from Dexuan +Origin: https://patchwork.kernel.org/patch/9534107/ --- drivers/hv/ring_buffer.c | 1 + - drivers/net/hyperv/netvsc.c | 2 ++ + drivers/net/hyperv/netvsc.c | 6 ++++++ include/linux/hyperv.h | 32 ++++++++++++++++++++++++++++++-- - 3 files changed, 33 insertions(+), 2 deletions(-) + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index cd49cb17eb7f..308dbda700eb 100644 @@ -47,18 +46,29 @@ index cd49cb17eb7f..308dbda700eb 100644 next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc, sizeof(desc), diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c -index 720b5fa9e625..9cd74817b09c 100644 +index 720b5fa9e625..c2ac39a940f7 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c -@@ -1288,6 +1288,8 @@ void netvsc_channel_cb(void *context) +@@ -1288,6 +1288,9 @@ void netvsc_channel_cb(void *context) ndev = hv_get_drvdata(device); buffer = get_per_channel_state(channel); ++ /* commit_rd_index() -> hv_signal_on_read() needs this. */ + init_cached_read_index(channel); + do { desc = get_next_pkt_raw(channel); if (desc != NULL) { +@@ -1340,6 +1343,9 @@ void netvsc_channel_cb(void *context) + + bufferlen = bytes_recvd; + } ++ ++ init_cached_read_index(channel); ++ + } while (1); + + if (bufferlen > NETVSC_PACKET_SIZE) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 5343b7406acc..e34da6846348 100644 --- a/include/linux/hyperv.h diff --git a/alpine/kernel/patches-4.9/0010-Drivers-hv-vss-Improve-log-messages.patch b/alpine/kernel/patches-4.9/0010-Drivers-hv-vss-Improve-log-messages.patch new file mode 100644 index 000000000..1f007ae37 --- /dev/null +++ b/alpine/kernel/patches-4.9/0010-Drivers-hv-vss-Improve-log-messages.patch @@ -0,0 +1,104 @@ +From e87bfb9b2b1f3e79252b25261a033e51a976fb49 Mon Sep 17 00:00:00 2001 +From: Alex Ng +Date: Sun, 6 Nov 2016 13:14:10 -0800 +Subject: [PATCH 10/12] Drivers: hv: vss: Improve log messages. + +Adding log messages to help troubleshoot error cases and transaction +handling. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +(cherry picked from commit 23d2cc0c29eb0e7c6fe4cac88098306c31c40208) +--- + drivers/hv/hv_snapshot.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c +index a6707133c297..5c95ba1e2ecf 100644 +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -120,7 +120,7 @@ static int vss_handle_handshake(struct hv_vss_msg *vss_msg) + default: + return -EINVAL; + } +- pr_debug("VSS: userspace daemon ver. %d connected\n", dm_reg_value); ++ pr_info("VSS: userspace daemon ver. %d connected\n", dm_reg_value); + return 0; + } + +@@ -128,8 +128,10 @@ static int vss_on_msg(void *msg, int len) + { + struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg; + +- if (len != sizeof(*vss_msg)) ++ if (len != sizeof(*vss_msg)) { ++ pr_debug("VSS: Message size does not match length\n"); + return -EINVAL; ++ } + + if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER || + vss_msg->vss_hdr.operation == VSS_OP_REGISTER1) { +@@ -137,8 +139,11 @@ static int vss_on_msg(void *msg, int len) + * Don't process registration messages if we're in the middle + * of a transaction processing. + */ +- if (vss_transaction.state > HVUTIL_READY) ++ if (vss_transaction.state > HVUTIL_READY) { ++ pr_debug("VSS: Got unexpected registration request\n"); + return -EINVAL; ++ } ++ + return vss_handle_handshake(vss_msg); + } else if (vss_transaction.state == HVUTIL_USERSPACE_REQ) { + vss_transaction.state = HVUTIL_USERSPACE_RECV; +@@ -155,7 +160,7 @@ static int vss_on_msg(void *msg, int len) + } + } else { + /* This is a spurious call! */ +- pr_warn("VSS: Transaction not active\n"); ++ pr_debug("VSS: Transaction not active\n"); + return -EINVAL; + } + return 0; +@@ -168,8 +173,10 @@ static void vss_send_op(void) + struct hv_vss_msg *vss_msg; + + /* The transaction state is wrong. */ +- if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) ++ if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) { ++ pr_debug("VSS: Unexpected attempt to send to daemon\n"); + return; ++ } + + vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL); + if (!vss_msg) +@@ -210,9 +217,13 @@ static void vss_handle_request(struct work_struct *dummy) + case VSS_OP_HOT_BACKUP: + if (vss_transaction.state < HVUTIL_READY) { + /* Userspace is not registered yet */ ++ pr_debug("VSS: Not ready for request.\n"); + vss_respond_to_host(HV_E_FAIL); + return; + } ++ ++ pr_debug("VSS: Received request for op code: %d\n", ++ vss_transaction.msg->vss_hdr.operation); + vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED; + vss_send_op(); + return; +@@ -353,8 +364,10 @@ hv_vss_init(struct hv_util_service *srv) + + hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL, + vss_on_msg, vss_on_reset); +- if (!hvt) ++ if (!hvt) { ++ pr_warn("VSS: Failed to initialize transport\n"); + return -EFAULT; ++ } + + return 0; + } +-- +2.11.0 + diff --git a/alpine/kernel/patches-4.9/0011-Drivers-hv-vss-Operation-timeouts-should-match-host-.patch b/alpine/kernel/patches-4.9/0011-Drivers-hv-vss-Operation-timeouts-should-match-host-.patch new file mode 100644 index 000000000..e952a8361 --- /dev/null +++ b/alpine/kernel/patches-4.9/0011-Drivers-hv-vss-Operation-timeouts-should-match-host-.patch @@ -0,0 +1,47 @@ +From b422d8d6fe1a29c9cc856c5e6e6bb081e30a11e9 Mon Sep 17 00:00:00 2001 +From: Alex Ng +Date: Sun, 6 Nov 2016 13:14:11 -0800 +Subject: [PATCH 11/12] Drivers: hv: vss: Operation timeouts should match host + expectation + +Increase the timeout of backup operations. When system is under I/O load, +it needs more time to freeze. These timeout values should also match the +host timeout values more closely. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +(cherry picked from commit b357fd3908c1191f2f56e38aa77f2aecdae18bc8) +--- + drivers/hv/hv_snapshot.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c +index 5c95ba1e2ecf..eee238cc60bd 100644 +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -31,7 +31,10 @@ + #define VSS_MINOR 0 + #define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR) + +-#define VSS_USERSPACE_TIMEOUT (msecs_to_jiffies(10 * 1000)) ++/* ++ * Timeout values are based on expecations from host ++ */ ++#define VSS_FREEZE_TIMEOUT (15 * 60) + + /* + * Global state maintained for transaction that is being processed. For a class +@@ -186,7 +189,8 @@ static void vss_send_op(void) + + vss_transaction.state = HVUTIL_USERSPACE_REQ; + +- schedule_delayed_work(&vss_timeout_work, VSS_USERSPACE_TIMEOUT); ++ schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ? ++ VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ); + + rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL); + if (rc) { +-- +2.11.0 + diff --git a/alpine/kernel/patches-4.9/0012-Drivers-hv-vmbus-Use-all-supported-IC-versions-to-ne.patch b/alpine/kernel/patches-4.9/0012-Drivers-hv-vmbus-Use-all-supported-IC-versions-to-ne.patch new file mode 100644 index 000000000..6ad819f47 --- /dev/null +++ b/alpine/kernel/patches-4.9/0012-Drivers-hv-vmbus-Use-all-supported-IC-versions-to-ne.patch @@ -0,0 +1,487 @@ +From 3cbf33b27c52d640801d8482fa2b7b8376addff5 Mon Sep 17 00:00:00 2001 +From: Alex Ng +Date: Wed, 18 Jan 2017 12:02:44 -0800 +Subject: [PATCH 12/12] Drivers: hv: vmbus: Use all supported IC versions to + negotiate + +Previously, we were assuming that each IC protocol version was tied to a +specific host version. For example, some Windows 10 preview hosts only +support v3 TimeSync even though driver assumes v4 is supported by all +Windows 10 hosts. + +The guest will stop trying to negotiate even though older supported +versions may still be offered by the host. + +Make IC version negotiation more robust by going through all versions +that are supported by the guest. + +Fixes: 3da0401b4d0e ("Drivers: hv: utils: Fix the mapping between host +version and protocol to use") + +Reported-by: Rolf Neugebauer +Signed-off-by: Alex Ng +Origin: Email from Alex Ng +--- + drivers/hv/channel_mgmt.c | 78 ++++++++++++++++++++++++++------------- + drivers/hv/hv_fcopy.c | 20 +++++++--- + drivers/hv/hv_kvp.c | 41 +++++++++------------ + drivers/hv/hv_snapshot.c | 18 +++++++-- + drivers/hv/hv_util.c | 94 +++++++++++++++++++++++++---------------------- + include/linux/hyperv.h | 7 ++-- + 6 files changed, 152 insertions(+), 106 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 8f3d9f787288..253e17c78c58 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -179,33 +179,34 @@ static u16 hv_get_dev_type(const struct vmbus_channel *channel) + * @buf: Raw buffer channel data + * + * @icmsghdrp is of type &struct icmsg_hdr. +- * @negop is of type &struct icmsg_negotiate. + * Set up and fill in default negotiate response message. + * +- * The fw_version specifies the framework version that +- * we can support and srv_version specifies the service +- * version we can support. ++ * The fw_version and fw_vercnt specifies the framework version that ++ * we can support. ++ * ++ * The srv_version and srv_vercnt specifies the service ++ * versions we can support. ++ * ++ * Versions are given in decreasing order. ++ * ++ * nego_fw_version and nego_srv_version store the selected protocol versions. + * + * Mainly used by Hyper-V drivers. + */ + bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, +- struct icmsg_negotiate *negop, u8 *buf, +- int fw_version, int srv_version) ++ u8 *buf, const int *fw_version, int fw_vercnt, ++ const int *srv_version, int srv_vercnt, ++ int *nego_fw_version, int *nego_srv_version) + { + int icframe_major, icframe_minor; + int icmsg_major, icmsg_minor; + int fw_major, fw_minor; + int srv_major, srv_minor; +- int i; ++ int i, j; + bool found_match = false; ++ struct icmsg_negotiate *negop; + + icmsghdrp->icmsgsize = 0x10; +- fw_major = (fw_version >> 16); +- fw_minor = (fw_version & 0xFFFF); +- +- srv_major = (srv_version >> 16); +- srv_minor = (srv_version & 0xFFFF); +- + negop = (struct icmsg_negotiate *)&buf[ + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; +@@ -221,13 +222,22 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, + * support. + */ + +- for (i = 0; i < negop->icframe_vercnt; i++) { +- if ((negop->icversion_data[i].major == fw_major) && +- (negop->icversion_data[i].minor == fw_minor)) { +- icframe_major = negop->icversion_data[i].major; +- icframe_minor = negop->icversion_data[i].minor; +- found_match = true; ++ for (i = 0; i < fw_vercnt; i++) { ++ fw_major = (fw_version[i] >> 16); ++ fw_minor = (fw_version[i] & 0xFFFF); ++ ++ for (j = 0; j < negop->icframe_vercnt; j++) { ++ if ((negop->icversion_data[j].major == fw_major) && ++ (negop->icversion_data[j].minor == fw_minor)) { ++ icframe_major = negop->icversion_data[j].major; ++ icframe_minor = negop->icversion_data[j].minor; ++ found_match = true; ++ break; ++ } + } ++ ++ if (found_match) ++ break; + } + + if (!found_match) +@@ -235,14 +245,24 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, + + found_match = false; + +- for (i = negop->icframe_vercnt; +- (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { +- if ((negop->icversion_data[i].major == srv_major) && +- (negop->icversion_data[i].minor == srv_minor)) { +- icmsg_major = negop->icversion_data[i].major; +- icmsg_minor = negop->icversion_data[i].minor; +- found_match = true; ++ for (i = 0; i < srv_vercnt; i++) { ++ srv_major = (srv_version[i] >> 16); ++ srv_minor = (srv_version[i] & 0xFFFF); ++ ++ for (j = negop->icframe_vercnt; ++ (j < negop->icframe_vercnt + negop->icmsg_vercnt); ++ j++) { ++ if ((negop->icversion_data[j].major == srv_major) && ++ (negop->icversion_data[j].minor == srv_minor)) { ++ icmsg_major = negop->icversion_data[j].major; ++ icmsg_minor = negop->icversion_data[j].minor; ++ found_match = true; ++ break; ++ } + } ++ ++ if (found_match) ++ break; + } + + /* +@@ -259,6 +279,12 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, + negop->icmsg_vercnt = 1; + } + ++ if (nego_fw_version) ++ *nego_fw_version = (icframe_major << 16) | icframe_minor; ++ ++ if (nego_srv_version) ++ *nego_srv_version = (icmsg_major << 16) | icmsg_minor; ++ + negop->icversion_data[0].major = icframe_major; + negop->icversion_data[0].minor = icframe_minor; + negop->icversion_data[1].major = icmsg_major; +diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c +index 8b2ba98831ec..3e3a633cab58 100644 +--- a/drivers/hv/hv_fcopy.c ++++ b/drivers/hv/hv_fcopy.c +@@ -31,6 +31,16 @@ + #define WIN8_SRV_MINOR 1 + #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) + ++#define FCOPY_VER_COUNT 1 ++static const int fcopy_versions[] = { ++ WIN8_SRV_VERSION ++}; ++ ++#define FW_VER_COUNT 1 ++static const int fw_versions[] = { ++ UTIL_FW_VERSION ++}; ++ + /* + * Global state maintained for transaction that is being processed. + * For a class of integration services, including the "file copy service", +@@ -227,8 +237,6 @@ void hv_fcopy_onchannelcallback(void *context) + u64 requestid; + struct hv_fcopy_hdr *fcopy_msg; + struct icmsg_hdr *icmsghdr; +- struct icmsg_negotiate *negop = NULL; +- int util_fw_version; + int fcopy_srv_version; + + if (fcopy_transaction.state > HVUTIL_READY) +@@ -242,10 +250,10 @@ void hv_fcopy_onchannelcallback(void *context) + icmsghdr = (struct icmsg_hdr *)&recv_buffer[ + sizeof(struct vmbuspipe_hdr)]; + if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- util_fw_version = UTIL_FW_VERSION; +- fcopy_srv_version = WIN8_SRV_VERSION; +- vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer, +- util_fw_version, fcopy_srv_version); ++ vmbus_prep_negotiate_resp(icmsghdr, recv_buffer, ++ fw_versions, FW_VER_COUNT, ++ fcopy_versions, FCOPY_VER_COUNT, ++ NULL, &fcopy_srv_version); + } else { + fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ + sizeof(struct vmbuspipe_hdr) + +diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c +index 5e1fdc8d32ab..70c28b8806de 100644 +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -46,6 +46,19 @@ + #define WIN8_SRV_MINOR 0 + #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) + ++#define KVP_VER_COUNT 3 ++static const int kvp_versions[] = { ++ WIN8_SRV_VERSION, ++ WIN7_SRV_VERSION, ++ WS2008_SRV_VERSION ++}; ++ ++#define FW_VER_COUNT 2 ++static const int fw_versions[] = { ++ UTIL_FW_VERSION, ++ UTIL_WS2K8_FW_VERSION ++}; ++ + /* + * Global state maintained for transaction that is being processed. For a class + * of integration services, including the "KVP service", the specified protocol +@@ -609,8 +622,6 @@ void hv_kvp_onchannelcallback(void *context) + struct hv_kvp_msg *kvp_msg; + + struct icmsg_hdr *icmsghdrp; +- struct icmsg_negotiate *negop = NULL; +- int util_fw_version; + int kvp_srv_version; + static enum {NEGO_NOT_STARTED, + NEGO_IN_PROGRESS, +@@ -639,28 +650,10 @@ void hv_kvp_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- /* +- * Based on the host, select appropriate +- * framework and service versions we will +- * negotiate. +- */ +- switch (vmbus_proto_version) { +- case (VERSION_WS2008): +- util_fw_version = UTIL_WS2K8_FW_VERSION; +- kvp_srv_version = WS2008_SRV_VERSION; +- break; +- case (VERSION_WIN7): +- util_fw_version = UTIL_FW_VERSION; +- kvp_srv_version = WIN7_SRV_VERSION; +- break; +- default: +- util_fw_version = UTIL_FW_VERSION; +- kvp_srv_version = WIN8_SRV_VERSION; +- } +- vmbus_prep_negotiate_resp(icmsghdrp, negop, +- recv_buffer, util_fw_version, +- kvp_srv_version); +- ++ vmbus_prep_negotiate_resp(icmsghdrp, ++ recv_buffer, fw_versions, FW_VER_COUNT, ++ kvp_versions, KVP_VER_COUNT, ++ NULL, &kvp_srv_version); + } else { + kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ + sizeof(struct vmbuspipe_hdr) + +diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c +index eee238cc60bd..8e62bf7f6265 100644 +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -31,6 +31,16 @@ + #define VSS_MINOR 0 + #define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR) + ++#define VSS_VER_COUNT 1 ++static const int vss_versions[] = { ++ VSS_VERSION ++}; ++ ++#define FW_VER_COUNT 1 ++static const int fw_versions[] = { ++ UTIL_FW_VERSION ++}; ++ + /* + * Timeout values are based on expecations from host + */ +@@ -296,7 +306,6 @@ void hv_vss_onchannelcallback(void *context) + + + struct icmsg_hdr *icmsghdrp; +- struct icmsg_negotiate *negop = NULL; + + if (vss_transaction.state > HVUTIL_READY) + return; +@@ -309,9 +318,10 @@ void hv_vss_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- vmbus_prep_negotiate_resp(icmsghdrp, negop, +- recv_buffer, UTIL_FW_VERSION, +- VSS_VERSION); ++ vmbus_prep_negotiate_resp(icmsghdrp, ++ recv_buffer, fw_versions, FW_VER_COUNT, ++ vss_versions, VSS_VER_COUNT, ++ NULL, NULL); + } else { + vss_msg = (struct hv_vss_msg *)&recv_buffer[ + sizeof(struct vmbuspipe_hdr) + +diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c +index e7707747f56d..f3797c07be10 100644 +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -57,7 +57,31 @@ + static int sd_srv_version; + static int ts_srv_version; + static int hb_srv_version; +-static int util_fw_version; ++ ++#define SD_VER_COUNT 2 ++static const int sd_versions[] = { ++ SD_VERSION, ++ SD_VERSION_1 ++}; ++ ++#define TS_VER_COUNT 3 ++static const int ts_versions[] = { ++ TS_VERSION, ++ TS_VERSION_3, ++ TS_VERSION_1 ++}; ++ ++#define HB_VER_COUNT 2 ++static const int hb_versions[] = { ++ HB_VERSION, ++ HB_VERSION_1 ++}; ++ ++#define FW_VER_COUNT 2 ++static const int fw_versions[] = { ++ UTIL_FW_VERSION, ++ UTIL_WS2K8_FW_VERSION ++}; + + static void shutdown_onchannelcallback(void *context); + static struct hv_util_service util_shutdown = { +@@ -118,7 +142,6 @@ static void shutdown_onchannelcallback(void *context) + struct shutdown_msg_data *shutdown_msg; + + struct icmsg_hdr *icmsghdrp; +- struct icmsg_negotiate *negop = NULL; + + vmbus_recvpacket(channel, shut_txf_buf, + PAGE_SIZE, &recvlen, &requestid); +@@ -128,9 +151,14 @@ static void shutdown_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- vmbus_prep_negotiate_resp(icmsghdrp, negop, +- shut_txf_buf, util_fw_version, +- sd_srv_version); ++ if (vmbus_prep_negotiate_resp(icmsghdrp, shut_txf_buf, ++ fw_versions, FW_VER_COUNT, ++ sd_versions, SD_VER_COUNT, ++ NULL, &sd_srv_version)) { ++ pr_info("Shutdown IC version %d.%d\n", ++ sd_srv_version >> 16, ++ sd_srv_version & 0xFFFF); ++ } + } else { + shutdown_msg = + (struct shutdown_msg_data *)&shut_txf_buf[ +@@ -253,7 +281,6 @@ static void timesync_onchannelcallback(void *context) + struct ictimesync_data *timedatap; + struct ictimesync_ref_data *refdata; + u8 *time_txf_buf = util_timesynch.recv_buffer; +- struct icmsg_negotiate *negop = NULL; + + vmbus_recvpacket(channel, time_txf_buf, + PAGE_SIZE, &recvlen, &requestid); +@@ -263,12 +290,14 @@ static void timesync_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- vmbus_prep_negotiate_resp(icmsghdrp, negop, +- time_txf_buf, +- util_fw_version, +- ts_srv_version); +- pr_info("Using TimeSync version %d.%d\n", +- ts_srv_version >> 16, ts_srv_version & 0xFFFF); ++ if (vmbus_prep_negotiate_resp(icmsghdrp, time_txf_buf, ++ fw_versions, FW_VER_COUNT, ++ ts_versions, TS_VER_COUNT, ++ NULL, &ts_srv_version)) { ++ pr_info("TimeSync version %d.%d\n", ++ ts_srv_version >> 16, ++ ts_srv_version & 0xFFFF); ++ } + } else { + if (ts_srv_version > TS_VERSION_3) { + refdata = (struct ictimesync_ref_data *) +@@ -312,7 +341,6 @@ static void heartbeat_onchannelcallback(void *context) + struct icmsg_hdr *icmsghdrp; + struct heartbeat_msg_data *heartbeat_msg; + u8 *hbeat_txf_buf = util_heartbeat.recv_buffer; +- struct icmsg_negotiate *negop = NULL; + + while (1) { + +@@ -326,9 +354,16 @@ static void heartbeat_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { +- vmbus_prep_negotiate_resp(icmsghdrp, negop, +- hbeat_txf_buf, util_fw_version, +- hb_srv_version); ++ if (vmbus_prep_negotiate_resp(icmsghdrp, ++ hbeat_txf_buf, ++ fw_versions, FW_VER_COUNT, ++ hb_versions, HB_VER_COUNT, ++ NULL, &hb_srv_version)) { ++ ++ pr_info("Heartbeat version %d.%d\n", ++ hb_srv_version >> 16, ++ hb_srv_version & 0xFFFF); ++ } + } else { + heartbeat_msg = + (struct heartbeat_msg_data *)&hbeat_txf_buf[ +@@ -378,33 +413,6 @@ static int util_probe(struct hv_device *dev, + + hv_set_drvdata(dev, srv); + +- /* +- * Based on the host; initialize the framework and +- * service version numbers we will negotiate. +- */ +- switch (vmbus_proto_version) { +- case (VERSION_WS2008): +- util_fw_version = UTIL_WS2K8_FW_VERSION; +- sd_srv_version = SD_VERSION_1; +- ts_srv_version = TS_VERSION_1; +- hb_srv_version = HB_VERSION_1; +- break; +- case VERSION_WIN7: +- case VERSION_WIN8: +- case VERSION_WIN8_1: +- util_fw_version = UTIL_FW_VERSION; +- sd_srv_version = SD_VERSION; +- ts_srv_version = TS_VERSION_3; +- hb_srv_version = HB_VERSION; +- break; +- case VERSION_WIN10: +- default: +- util_fw_version = UTIL_FW_VERSION; +- sd_srv_version = SD_VERSION; +- ts_srv_version = TS_VERSION; +- hb_srv_version = HB_VERSION; +- } +- + ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0, + srv->util_cb, dev->channel); + if (ret) +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index e34da6846348..032322e4a73e 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1452,9 +1452,10 @@ struct hyperv_service_callback { + }; + + #define MAX_SRV_VER 0x7ffffff +-extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, +- struct icmsg_negotiate *, u8 *, int, +- int); ++extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, u8 *, ++ const int *, int, ++ const int *, int, ++ int *, int *); + + void hv_event_tasklet_disable(struct vmbus_channel *channel); + void hv_event_tasklet_enable(struct vmbus_channel *channel); +-- +2.11.0 +