aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/hv_kvp.c
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2013-07-02 10:31:30 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-26 16:40:41 -0700
commit6741335bc7294548ac95cb1f4671991ff30da193 (patch)
treeb5930cd4e558ff76838966e8a23941352acf9a0e /drivers/hv/hv_kvp.c
parenttools: hv: Check return value of setsockopt call (diff)
downloadlinux-dev-6741335bc7294548ac95cb1f4671991ff30da193.tar.xz
linux-dev-6741335bc7294548ac95cb1f4671991ff30da193.zip
Drivers: hv: util: Fix a bug in version negotiation code for util services
The current code picked the highest version advertised by the host. WS2012 R2 has implemented a protocol version for KVP that is not compatible with prior protocol versions of KVP. Fix the bug in the current code by explicitly specifying the protocol version that the guest can support. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/hv_kvp.c')
-rw-r--r--drivers/hv/hv_kvp.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index ed50e9e83c61..53127209a404 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -29,6 +29,16 @@
#include <linux/hyperv.h>
+/*
+ * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
+ */
+#define WIN7_SRV_MAJOR 3
+#define WIN7_SRV_MINOR 0
+#define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
+
+#define WIN8_SRV_MAJOR 4
+#define WIN8_SRV_MINOR 0
+#define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
/*
* Global state maintained for transaction that is being processed.
@@ -593,8 +603,19 @@ void hv_kvp_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ /*
+ * We start with win8 version and if the host cannot
+ * support that we use the previous version.
+ */
+ if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
+ recv_buffer, UTIL_FW_MAJOR_MINOR,
+ WIN8_SRV_MAJOR_MINOR))
+ goto done;
+
vmbus_prep_negotiate_resp(icmsghdrp, negop,
- recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
+ recv_buffer, UTIL_FW_MAJOR_MINOR,
+ WIN7_SRV_MAJOR_MINOR);
+
} else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
@@ -626,6 +647,7 @@ void hv_kvp_onchannelcallback(void *context)
return;
}
+done:
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;