mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-11-02 01:16:05 +00:00
Move kernel directory to top level
Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
From fb4ee21f744b2639a1a7d495a732198a3e9c96ec 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 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
|
||||
alternative end point address within a namespace.
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@docker.com>
|
||||
---
|
||||
net/vmw_vsock/af_vsock.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
|
||||
index 8a398b3fb532..0edc54c5e6ed 100644
|
||||
--- a/net/vmw_vsock/af_vsock.c
|
||||
+++ b/net/vmw_vsock/af_vsock.c
|
||||
@@ -1852,6 +1852,9 @@ static const struct proto_ops vsock_stream_ops = {
|
||||
static int vsock_create(struct net *net, struct socket *sock,
|
||||
int protocol, int kern)
|
||||
{
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ return -EAFNOSUPPORT;
|
||||
+
|
||||
if (!sock)
|
||||
return -EINVAL;
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
1791
kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch
Normal file
1791
kernel/patches-4.9/0002-hv_sock-introduce-Hyper-V-Sockets.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
From 087c906e5cd36f32e8d0edcbea8a4cfb5bb98947 Mon Sep 17 00:00:00 2001
|
||||
From: Rolf Neugebauer <rolf.neugebauer@gmail.com>
|
||||
Date: Mon, 23 May 2016 18:55:45 +0100
|
||||
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
|
||||
there doesn't seem to be an easy way to check for registered services,
|
||||
disable the pr_info() completely.
|
||||
|
||||
Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index 1bc1d4795243..db5bccf4fa7e 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -169,7 +169,6 @@ static u16 hv_get_dev_type(const struct vmbus_channel *channel)
|
||||
if (!uuid_le_cmp(*guid, vmbus_devs[i].guid))
|
||||
return i;
|
||||
}
|
||||
- pr_info("Unknown GUID: %pUl\n", guid);
|
||||
return i;
|
||||
}
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 59043b28040811e2af89841dbb4d3b9445ae67e1 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:07 -0800
|
||||
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
|
||||
and default to using the latest protocol if the host is unknown or new.
|
||||
|
||||
Signed-off-by: Alex Ng <alexng@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(cherry picked from commit 3da0401b4d0e17aea7526db0235d98fa535d903e)
|
||||
---
|
||||
drivers/hv/hv_util.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
|
||||
index bcd06306f3e8..e7707747f56d 100644
|
||||
--- a/drivers/hv/hv_util.c
|
||||
+++ b/drivers/hv/hv_util.c
|
||||
@@ -389,16 +389,19 @@ static int util_probe(struct hv_device *dev,
|
||||
ts_srv_version = TS_VERSION_1;
|
||||
hb_srv_version = HB_VERSION_1;
|
||||
break;
|
||||
- case(VERSION_WIN10):
|
||||
+ 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;
|
||||
+ 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_3;
|
||||
+ ts_srv_version = TS_VERSION;
|
||||
hb_srv_version = HB_VERSION;
|
||||
}
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From ff8f8f00ebc17ee2cabc316ad610188db1e8fe5d Mon Sep 17 00:00:00 2001
|
||||
From: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||
Date: Tue, 17 Jan 2017 18:13:51 +0000
|
||||
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
|
||||
ip_summed field.
|
||||
|
||||
With the above commits, the flags are set to VIRTIO_NET_HDR_F_DATA_VALID
|
||||
when ip_summed == CHECKSUM_UNNECESSARY, thus treating it differently to
|
||||
ip_summed == CHECKSUM_NONE, which should be the same.
|
||||
|
||||
Further, the virtio spec 1.0 / CS04 explicitly says that
|
||||
VIRTIO_NET_HDR_F_DATA_VALID must not be set by the driver.
|
||||
|
||||
Fixes: fd2a0437dc33 ("virtio_net: introduce virtio_net_hdr_{from,to}_skb")
|
||||
Fixes: e858fae2b0b8 (" virtio_net: use common code for virtio_net_hdr and skb GSO conversion")
|
||||
Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||
Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
(cherry picked from commit 501db511397fd6efff3aa5b4e8de415b55559550)
|
||||
---
|
||||
include/linux/virtio_net.h | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
|
||||
index 1c912f85e041..40914bb396e7 100644
|
||||
--- a/include/linux/virtio_net.h
|
||||
+++ b/include/linux/virtio_net.h
|
||||
@@ -91,8 +91,6 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
|
||||
skb_checksum_start_offset(skb));
|
||||
hdr->csum_offset = __cpu_to_virtio16(little_endian,
|
||||
skb->csum_offset);
|
||||
- } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
|
||||
- hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
|
||||
} /* else everything is zero */
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
From dedfc354773877960dcf6c8a926faa4a94803ec5 Mon Sep 17 00:00:00 2001
|
||||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:16 -0800
|
||||
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
|
||||
guest in mounting a DOS attack is if the guest generates interrupts
|
||||
to the host when the host is not expecting it. If these "spurious"
|
||||
interrupts reach a certain rate, the host can throttle the guest to
|
||||
minimize the impact. The host computation of the "expected number
|
||||
of interrupts" is strictly based on the ring transitions. Until
|
||||
the host logic is fixed, base the guest logic to interrupt solely
|
||||
on the ring state.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(cherry picked from commit 74198eb4a42c4a3c4fbef08fa01a291a282f7c2e)
|
||||
---
|
||||
drivers/hv/channel.c | 23 ++++++++++++++++++++---
|
||||
drivers/hv/channel_mgmt.c | 2 --
|
||||
drivers/hv/ring_buffer.c | 7 -------
|
||||
3 files changed, 20 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 16f91c8490fe..5e482d7f60cb 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -676,10 +676,18 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||
* NOTE: in this case, the hvsock channel is an exception, because
|
||||
* it looks the host side's hvsock implementation has a throttling
|
||||
* mechanism which can hurt the performance otherwise.
|
||||
+ *
|
||||
+ * KYS: Oct. 30, 2016:
|
||||
+ * It looks like Windows hosts have logic to deal with DOS attacks that
|
||||
+ * can be triggered if it receives interrupts when it is not expecting
|
||||
+ * the interrupt. The host expects interrupts only when the ring
|
||||
+ * transitions from empty to non-empty (or full to non full on the guest
|
||||
+ * to host ring).
|
||||
+ * So, base the signaling decision solely on the ring state until the
|
||||
+ * host logic is fixed.
|
||||
*/
|
||||
|
||||
- if (((ret == 0) && kick_q && signal) ||
|
||||
- (ret && !is_hvsock_channel(channel)))
|
||||
+ if (((ret == 0) && signal))
|
||||
vmbus_setevent(channel);
|
||||
|
||||
return ret;
|
||||
@@ -786,9 +794,18 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
* If we cannot write to the ring-buffer; signal the host
|
||||
* even if we may not have written anything. This is a rare
|
||||
* enough condition that it should not matter.
|
||||
+ *
|
||||
+ * KYS: Oct. 30, 2016:
|
||||
+ * It looks like Windows hosts have logic to deal with DOS attacks that
|
||||
+ * can be triggered if it receives interrupts when it is not expecting
|
||||
+ * the interrupt. The host expects interrupts only when the ring
|
||||
+ * transitions from empty to non-empty (or full to non full on the guest
|
||||
+ * to host ring).
|
||||
+ * So, base the signaling decision solely on the ring state until the
|
||||
+ * host logic is fixed.
|
||||
*/
|
||||
|
||||
- if (((ret == 0) && kick_q && signal) || (ret))
|
||||
+ if (((ret == 0) && signal))
|
||||
vmbus_setevent(channel);
|
||||
|
||||
return ret;
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index db5bccf4fa7e..8f3d9f787288 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -448,8 +448,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||
}
|
||||
|
||||
dev_type = hv_get_dev_type(newchannel);
|
||||
- if (dev_type == HV_NIC)
|
||||
- set_channel_signal_state(newchannel, HV_SIGNAL_POLICY_EXPLICIT);
|
||||
|
||||
init_vp_index(newchannel, dev_type);
|
||||
|
||||
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
|
||||
index 08043da1a61c..5d11d93eedf4 100644
|
||||
--- a/drivers/hv/ring_buffer.c
|
||||
+++ b/drivers/hv/ring_buffer.c
|
||||
@@ -75,13 +75,6 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi,
|
||||
if (READ_ONCE(rbi->ring_buffer->interrupt_mask))
|
||||
return false;
|
||||
|
||||
- /*
|
||||
- * When the client wants to control signaling,
|
||||
- * we only honour the host interrupt mask.
|
||||
- */
|
||||
- if (policy == HV_SIGNAL_POLICY_EXPLICIT)
|
||||
- return true;
|
||||
-
|
||||
/* check interrupt_mask before read_index */
|
||||
virt_rmb();
|
||||
/*
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
From 59b43ccde9636cdb874156a6f6e570414eb3d67b Mon Sep 17 00:00:00 2001
|
||||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:17 -0800
|
||||
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.
|
||||
The currrent code determines the need to signal in the ringbuffer
|
||||
code and actually issues the signal elsewhere. This can result
|
||||
in the host viewing this interrupt as spurious since the host may also
|
||||
poll the channel. Make the necessary adjustments.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(cherry picked from commit 1f6ee4e7d83586c8b10bd4f2f4346353d04ce884)
|
||||
---
|
||||
drivers/hv/channel.c | 99 +++++------------------------------------------
|
||||
drivers/hv/hyperv_vmbus.h | 6 +--
|
||||
drivers/hv/ring_buffer.c | 30 +++++++++-----
|
||||
include/linux/hyperv.h | 1 +
|
||||
4 files changed, 35 insertions(+), 101 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 5e482d7f60cb..8a8148f7b842 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -39,7 +39,7 @@
|
||||
* vmbus_setevent- Trigger an event notification on the specified
|
||||
* channel.
|
||||
*/
|
||||
-static void vmbus_setevent(struct vmbus_channel *channel)
|
||||
+void vmbus_setevent(struct vmbus_channel *channel)
|
||||
{
|
||||
struct hv_monitor_page *monitorpage;
|
||||
|
||||
@@ -65,6 +65,7 @@ static void vmbus_setevent(struct vmbus_channel *channel)
|
||||
vmbus_set_event(channel);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vmbus_setevent);
|
||||
|
||||
/*
|
||||
* vmbus_open - Open the specified channel.
|
||||
@@ -635,8 +636,6 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||
u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
|
||||
struct kvec bufferlist[3];
|
||||
u64 aligned_data = 0;
|
||||
- int ret;
|
||||
- bool signal = false;
|
||||
bool lock = channel->acquire_ring_lock;
|
||||
int num_vecs = ((bufferlen != 0) ? 3 : 1);
|
||||
|
||||
@@ -656,41 +655,9 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||
bufferlist[2].iov_base = &aligned_data;
|
||||
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||
|
||||
- ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
|
||||
- &signal, lock, channel->signal_policy);
|
||||
-
|
||||
- /*
|
||||
- * Signalling the host is conditional on many factors:
|
||||
- * 1. The ring state changed from being empty to non-empty.
|
||||
- * This is tracked by the variable "signal".
|
||||
- * 2. The variable kick_q tracks if more data will be placed
|
||||
- * on the ring. We will not signal if more data is
|
||||
- * to be placed.
|
||||
- *
|
||||
- * Based on the channel signal state, we will decide
|
||||
- * which signaling policy will be applied.
|
||||
- *
|
||||
- * If we cannot write to the ring-buffer; signal the host
|
||||
- * even if we may not have written anything. This is a rare
|
||||
- * enough condition that it should not matter.
|
||||
- * NOTE: in this case, the hvsock channel is an exception, because
|
||||
- * it looks the host side's hvsock implementation has a throttling
|
||||
- * mechanism which can hurt the performance otherwise.
|
||||
- *
|
||||
- * KYS: Oct. 30, 2016:
|
||||
- * It looks like Windows hosts have logic to deal with DOS attacks that
|
||||
- * can be triggered if it receives interrupts when it is not expecting
|
||||
- * the interrupt. The host expects interrupts only when the ring
|
||||
- * transitions from empty to non-empty (or full to non full on the guest
|
||||
- * to host ring).
|
||||
- * So, base the signaling decision solely on the ring state until the
|
||||
- * host logic is fixed.
|
||||
- */
|
||||
-
|
||||
- if (((ret == 0) && signal))
|
||||
- vmbus_setevent(channel);
|
||||
+ return hv_ringbuffer_write(channel, bufferlist, num_vecs,
|
||||
+ lock, kick_q);
|
||||
|
||||
- return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vmbus_sendpacket_ctl);
|
||||
|
||||
@@ -731,7 +698,6 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
u32 flags,
|
||||
bool kick_q)
|
||||
{
|
||||
- int ret;
|
||||
int i;
|
||||
struct vmbus_channel_packet_page_buffer desc;
|
||||
u32 descsize;
|
||||
@@ -739,7 +705,6 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
u32 packetlen_aligned;
|
||||
struct kvec bufferlist[3];
|
||||
u64 aligned_data = 0;
|
||||
- bool signal = false;
|
||||
bool lock = channel->acquire_ring_lock;
|
||||
|
||||
if (pagecount > MAX_PAGE_BUFFER_COUNT)
|
||||
@@ -777,38 +742,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, lock, channel->signal_policy);
|
||||
-
|
||||
- /*
|
||||
- * Signalling the host is conditional on many factors:
|
||||
- * 1. The ring state changed from being empty to non-empty.
|
||||
- * This is tracked by the variable "signal".
|
||||
- * 2. The variable kick_q tracks if more data will be placed
|
||||
- * on the ring. We will not signal if more data is
|
||||
- * to be placed.
|
||||
- *
|
||||
- * Based on the channel signal state, we will decide
|
||||
- * which signaling policy will be applied.
|
||||
- *
|
||||
- * If we cannot write to the ring-buffer; signal the host
|
||||
- * even if we may not have written anything. This is a rare
|
||||
- * enough condition that it should not matter.
|
||||
- *
|
||||
- * KYS: Oct. 30, 2016:
|
||||
- * It looks like Windows hosts have logic to deal with DOS attacks that
|
||||
- * can be triggered if it receives interrupts when it is not expecting
|
||||
- * the interrupt. The host expects interrupts only when the ring
|
||||
- * transitions from empty to non-empty (or full to non full on the guest
|
||||
- * to host ring).
|
||||
- * So, base the signaling decision solely on the ring state until the
|
||||
- * host logic is fixed.
|
||||
- */
|
||||
-
|
||||
- if (((ret == 0) && signal))
|
||||
- vmbus_setevent(channel);
|
||||
-
|
||||
- return ret;
|
||||
+ return hv_ringbuffer_write(channel, bufferlist, 3,
|
||||
+ lock, kick_q);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
|
||||
|
||||
@@ -839,12 +774,10 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
|
||||
u32 desc_size,
|
||||
void *buffer, u32 bufferlen, u64 requestid)
|
||||
{
|
||||
- int ret;
|
||||
u32 packetlen;
|
||||
u32 packetlen_aligned;
|
||||
struct kvec bufferlist[3];
|
||||
u64 aligned_data = 0;
|
||||
- bool signal = false;
|
||||
bool lock = channel->acquire_ring_lock;
|
||||
|
||||
packetlen = desc_size + bufferlen;
|
||||
@@ -865,13 +798,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, lock, channel->signal_policy);
|
||||
-
|
||||
- if (ret == 0 && signal)
|
||||
- vmbus_setevent(channel);
|
||||
-
|
||||
- return ret;
|
||||
+ return hv_ringbuffer_write(channel, bufferlist, 3,
|
||||
+ lock, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
|
||||
|
||||
@@ -883,14 +811,12 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
|
||||
struct hv_multipage_buffer *multi_pagebuffer,
|
||||
void *buffer, u32 bufferlen, u64 requestid)
|
||||
{
|
||||
- int ret;
|
||||
struct vmbus_channel_packet_multipage_buffer desc;
|
||||
u32 descsize;
|
||||
u32 packetlen;
|
||||
u32 packetlen_aligned;
|
||||
struct 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);
|
||||
@@ -930,13 +856,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, lock, channel->signal_policy);
|
||||
-
|
||||
- if (ret == 0 && signal)
|
||||
- vmbus_setevent(channel);
|
||||
-
|
||||
- return ret;
|
||||
+ return hv_ringbuffer_write(channel, bufferlist, 3,
|
||||
+ lock, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
|
||||
|
||||
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||
index a5b4442433c8..fa782e13c8da 100644
|
||||
--- a/drivers/hv/hyperv_vmbus.h
|
||||
+++ b/drivers/hv/hyperv_vmbus.h
|
||||
@@ -527,10 +527,10 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
|
||||
void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
|
||||
|
||||
-int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
|
||||
+int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
struct kvec *kv_list,
|
||||
- u32 kv_count, bool *signal, bool lock,
|
||||
- enum hv_signal_policy policy);
|
||||
+ u32 kv_count, bool lock,
|
||||
+ bool kick_q);
|
||||
|
||||
int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
|
||||
void *buffer, u32 buflen, u32 *buffer_actual_len,
|
||||
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
|
||||
index 5d11d93eedf4..4af71306d0ff 100644
|
||||
--- a/drivers/hv/ring_buffer.c
|
||||
+++ b/drivers/hv/ring_buffer.c
|
||||
@@ -66,14 +66,25 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
|
||||
* once the ring buffer is empty, it will clear the
|
||||
* interrupt_mask and re-check to see if new data has
|
||||
* arrived.
|
||||
+ *
|
||||
+ * KYS: Oct. 30, 2016:
|
||||
+ * It looks like Windows hosts have logic to deal with DOS attacks that
|
||||
+ * can be triggered if it receives interrupts when it is not expecting
|
||||
+ * the interrupt. The host expects interrupts only when the ring
|
||||
+ * transitions from empty to non-empty (or full to non full on the guest
|
||||
+ * to host ring).
|
||||
+ * So, base the signaling decision solely on the ring state until the
|
||||
+ * host logic is fixed.
|
||||
*/
|
||||
|
||||
-static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi,
|
||||
- enum hv_signal_policy policy)
|
||||
+static void hv_signal_on_write(u32 old_write, struct vmbus_channel *channel,
|
||||
+ bool kick_q)
|
||||
{
|
||||
+ struct hv_ring_buffer_info *rbi = &channel->outbound;
|
||||
+
|
||||
virt_mb();
|
||||
if (READ_ONCE(rbi->ring_buffer->interrupt_mask))
|
||||
- return false;
|
||||
+ return;
|
||||
|
||||
/* check interrupt_mask before read_index */
|
||||
virt_rmb();
|
||||
@@ -82,9 +93,9 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi,
|
||||
* ring transitions from being empty to non-empty.
|
||||
*/
|
||||
if (old_write == READ_ONCE(rbi->ring_buffer->read_index))
|
||||
- return true;
|
||||
+ vmbus_setevent(channel);
|
||||
|
||||
- return false;
|
||||
+ return;
|
||||
}
|
||||
|
||||
/* Get the next write location for the specified ring buffer. */
|
||||
@@ -273,9 +284,9 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
|
||||
}
|
||||
|
||||
/* Write to the ring buffer. */
|
||||
-int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||
- struct kvec *kv_list, u32 kv_count, bool *signal, bool lock,
|
||||
- enum hv_signal_policy policy)
|
||||
+int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
+ struct kvec *kv_list, u32 kv_count, bool lock,
|
||||
+ bool kick_q)
|
||||
{
|
||||
int i = 0;
|
||||
u32 bytes_avail_towrite;
|
||||
@@ -285,6 +296,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||
u32 old_write;
|
||||
u64 prev_indices = 0;
|
||||
unsigned long flags = 0;
|
||||
+ struct hv_ring_buffer_info *outring_info = &channel->outbound;
|
||||
|
||||
for (i = 0; i < kv_count; i++)
|
||||
totalbytes_towrite += kv_list[i].iov_len;
|
||||
@@ -337,7 +349,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
|
||||
if (lock)
|
||||
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
|
||||
|
||||
- *signal = hv_need_to_signal(old_write, outring_info, policy);
|
||||
+ hv_signal_on_write(old_write, channel, kick_q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 468e15e29f5f..9a2d657a7fe7 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -1447,6 +1447,7 @@ void hv_event_tasklet_enable(struct vmbus_channel *channel);
|
||||
|
||||
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
||||
|
||||
+void vmbus_setevent(struct vmbus_channel *channel);
|
||||
/*
|
||||
* Negotiated version with the Host.
|
||||
*/
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
From d77258d2dded3a5601ccd54edb6f99e035dc7b20 Mon Sep 17 00:00:00 2001
|
||||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:18 -0800
|
||||
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 -
|
||||
on th read path. The currrent code determines the need to signal in the
|
||||
ringbuffer code and actually issues the signal elsewhere. This can result
|
||||
in the host viewing this interrupt as spurious since the host may also
|
||||
poll the channel. Make the necessary adjustments.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(cherry picked from commit 3372592a140db69fd63837e81f048ab4abf8111e)
|
||||
---
|
||||
drivers/hv/channel.c | 11 ++---------
|
||||
drivers/hv/hyperv_vmbus.h | 4 ++--
|
||||
drivers/hv/ring_buffer.c | 7 ++++---
|
||||
include/linux/hyperv.h | 12 ++++++------
|
||||
4 files changed, 14 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 8a8148f7b842..5fb4c6d9209b 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -879,16 +879,9 @@ __vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||
u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
|
||||
bool raw)
|
||||
{
|
||||
- int ret;
|
||||
- bool signal = false;
|
||||
-
|
||||
- ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen,
|
||||
- buffer_actual_len, requestid, &signal, raw);
|
||||
+ return hv_ringbuffer_read(channel, buffer, bufferlen,
|
||||
+ buffer_actual_len, requestid, raw);
|
||||
|
||||
- if (signal)
|
||||
- vmbus_setevent(channel);
|
||||
-
|
||||
- return ret;
|
||||
}
|
||||
|
||||
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
|
||||
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||
index fa782e13c8da..2b13f2a0a71e 100644
|
||||
--- a/drivers/hv/hyperv_vmbus.h
|
||||
+++ b/drivers/hv/hyperv_vmbus.h
|
||||
@@ -532,9 +532,9 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
u32 kv_count, bool lock,
|
||||
bool kick_q);
|
||||
|
||||
-int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
|
||||
+int hv_ringbuffer_read(struct vmbus_channel *channel,
|
||||
void *buffer, u32 buflen, u32 *buffer_actual_len,
|
||||
- u64 *requestid, bool *signal, bool raw);
|
||||
+ u64 *requestid, bool raw);
|
||||
|
||||
void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info);
|
||||
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
|
||||
index 4af71306d0ff..cd49cb17eb7f 100644
|
||||
--- a/drivers/hv/ring_buffer.c
|
||||
+++ b/drivers/hv/ring_buffer.c
|
||||
@@ -353,9 +353,9 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
|
||||
+int hv_ringbuffer_read(struct vmbus_channel *channel,
|
||||
void *buffer, u32 buflen, u32 *buffer_actual_len,
|
||||
- u64 *requestid, bool *signal, bool raw)
|
||||
+ u64 *requestid, bool raw)
|
||||
{
|
||||
u32 bytes_avail_toread;
|
||||
u32 next_read_location = 0;
|
||||
@@ -364,6 +364,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
|
||||
u32 offset;
|
||||
u32 packetlen;
|
||||
int ret = 0;
|
||||
+ struct hv_ring_buffer_info *inring_info = &channel->inbound;
|
||||
|
||||
if (buflen <= 0)
|
||||
return -EINVAL;
|
||||
@@ -421,7 +422,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
|
||||
/* Update the read index */
|
||||
hv_set_next_read_location(inring_info, next_read_location);
|
||||
|
||||
- *signal = hv_need_to_signal_on_read(inring_info);
|
||||
+ hv_signal_on_read(channel);
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 9a2d657a7fe7..5343b7406acc 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -1480,10 +1480,11 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
|
||||
* there is room for the producer to send the pending packet.
|
||||
*/
|
||||
|
||||
-static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
|
||||
+static inline void hv_signal_on_read(struct vmbus_channel *channel)
|
||||
{
|
||||
u32 cur_write_sz;
|
||||
u32 pending_sz;
|
||||
+ struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
|
||||
/*
|
||||
* Issue a full memory barrier before making the signaling decision.
|
||||
@@ -1501,14 +1502,14 @@ static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
|
||||
pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
|
||||
/* If the other end is not blocked on write don't bother. */
|
||||
if (pending_sz == 0)
|
||||
- return false;
|
||||
+ return;
|
||||
|
||||
cur_write_sz = hv_get_bytes_to_write(rbi);
|
||||
|
||||
if (cur_write_sz >= pending_sz)
|
||||
- return true;
|
||||
+ vmbus_setevent(channel);
|
||||
|
||||
- return false;
|
||||
+ return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1590,8 +1591,7 @@ static inline void commit_rd_index(struct vmbus_channel *channel)
|
||||
virt_rmb();
|
||||
ring_info->ring_buffer->read_index = ring_info->priv_read_index;
|
||||
|
||||
- if (hv_need_to_signal_on_read(ring_info))
|
||||
- vmbus_set_event(channel);
|
||||
+ hv_signal_on_read(channel);
|
||||
}
|
||||
|
||||
struct vmpipe_proto_header {
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
From 21d5ad16c820d2e949ca80881986db3d228d8a33 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
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()")
|
||||
added the proper mb(), but removed the test "prev_write_sz < pending_sz"
|
||||
when making the signal decision.
|
||||
|
||||
As a result, the guest can signal the host unnecessarily,
|
||||
and then the host can throttle the guest because the host
|
||||
thinks the guest is buggy or malicious; finally the user
|
||||
running stress test can perceive intermittent freeze of
|
||||
the guest.
|
||||
|
||||
This patch brings back the test, and properly handles the
|
||||
in-place consumption APIs used by NetVSC (see get_next_pkt_raw(),
|
||||
put_pkt_raw() and commit_rd_index()).
|
||||
|
||||
Fixes: a389fcfd2cb5 ("Drivers: hv: vmbus: Fix signaling logic in hv_need_to_signal_on_read()")
|
||||
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||
Reported-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||
Tested-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
|
||||
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Cc: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Cc: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Origin: https://patchwork.kernel.org/patch/9534107/
|
||||
---
|
||||
drivers/hv/ring_buffer.c | 1 +
|
||||
drivers/net/hyperv/netvsc.c | 6 ++++++
|
||||
include/linux/hyperv.h | 32 ++++++++++++++++++++++++++++++--
|
||||
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
|
||||
--- a/drivers/hv/ring_buffer.c
|
||||
+++ b/drivers/hv/ring_buffer.c
|
||||
@@ -383,6 +383,7 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ init_cached_read_index(channel);
|
||||
next_read_location = hv_get_next_read_location(inring_info);
|
||||
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..c2ac39a940f7 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -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
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -128,6 +128,7 @@ struct hv_ring_buffer_info {
|
||||
u32 ring_data_startoffset;
|
||||
u32 priv_write_index;
|
||||
u32 priv_read_index;
|
||||
+ u32 cached_read_index;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -180,6 +181,19 @@ static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
|
||||
return write;
|
||||
}
|
||||
|
||||
+static inline u32 hv_get_cached_bytes_to_write(
|
||||
+ const struct hv_ring_buffer_info *rbi)
|
||||
+{
|
||||
+ u32 read_loc, write_loc, dsize, write;
|
||||
+
|
||||
+ dsize = rbi->ring_datasize;
|
||||
+ read_loc = rbi->cached_read_index;
|
||||
+ write_loc = rbi->ring_buffer->write_index;
|
||||
+
|
||||
+ write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
|
||||
+ read_loc - write_loc;
|
||||
+ return write;
|
||||
+}
|
||||
/*
|
||||
* VMBUS version is 32 bit entity broken up into
|
||||
* two 16 bit quantities: major_number. minor_number.
|
||||
@@ -1482,7 +1496,7 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
|
||||
|
||||
static inline void hv_signal_on_read(struct vmbus_channel *channel)
|
||||
{
|
||||
- u32 cur_write_sz;
|
||||
+ u32 cur_write_sz, cached_write_sz;
|
||||
u32 pending_sz;
|
||||
struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
|
||||
@@ -1506,12 +1520,24 @@ static inline void hv_signal_on_read(struct vmbus_channel *channel)
|
||||
|
||||
cur_write_sz = hv_get_bytes_to_write(rbi);
|
||||
|
||||
- if (cur_write_sz >= pending_sz)
|
||||
+ if (cur_write_sz < pending_sz)
|
||||
+ return;
|
||||
+
|
||||
+ cached_write_sz = hv_get_cached_bytes_to_write(rbi);
|
||||
+ if (cached_write_sz < pending_sz)
|
||||
vmbus_setevent(channel);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+init_cached_read_index(struct vmbus_channel *channel)
|
||||
+{
|
||||
+ struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
+
|
||||
+ rbi->cached_read_index = rbi->ring_buffer->read_index;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* An API to support in-place processing of incoming VMBUS packets.
|
||||
*/
|
||||
@@ -1573,6 +1599,8 @@ static inline void put_pkt_raw(struct vmbus_channel *channel,
|
||||
* This call commits the read index and potentially signals the host.
|
||||
* Here is the pattern for using the "in-place" consumption APIs:
|
||||
*
|
||||
+ * init_cached_read_index();
|
||||
+ *
|
||||
* while (get_next_pkt_raw() {
|
||||
* process the packet "in-place";
|
||||
* put_pkt_raw();
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
From e87bfb9b2b1f3e79252b25261a033e51a976fb49 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
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 <alexng@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(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
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From b422d8d6fe1a29c9cc856c5e6e6bb081e30a11e9 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
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 <alexng@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
(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
|
||||
|
||||
@@ -0,0 +1,487 @@
|
||||
From 3cbf33b27c52d640801d8482fa2b7b8376addff5 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
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 <rolf.neugebauer@docker.com>
|
||||
Signed-off-by: Alex Ng <alexng@messages.microsoft.com>
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user