Move kernel directory to top level

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack
2017-02-02 16:08:46 +00:00
parent f6c5995a6f
commit 3f81edee37
69 changed files with 32 additions and 33 deletions

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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