aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/channel_mgmt.c75
-rw-r--r--drivers/hv/hv_kvp.c24
-rw-r--r--drivers/hv/hv_snapshot.c18
-rw-r--r--drivers/hv/hv_util.c21
4 files changed, 100 insertions, 38 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 0df75908200e..12ec8c801b25 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry {
48 * @negop is of type &struct icmsg_negotiate. 48 * @negop is of type &struct icmsg_negotiate.
49 * Set up and fill in default negotiate response message. 49 * Set up and fill in default negotiate response message.
50 * 50 *
51 * The max_fw_version specifies the maximum framework version that 51 * The fw_version specifies the framework version that
52 * we can support and max _srv_version specifies the maximum service 52 * we can support and srv_version specifies the service
53 * version we can support. A special value MAX_SRV_VER can be 53 * version we can support.
54 * specified to indicate that we can handle the maximum version
55 * exposed by the host.
56 * 54 *
57 * Mainly used by Hyper-V drivers. 55 * Mainly used by Hyper-V drivers.
58 */ 56 */
59void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, 57bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
60 struct icmsg_negotiate *negop, u8 *buf, 58 struct icmsg_negotiate *negop, u8 *buf,
61 int max_fw_version, int max_srv_version) 59 int fw_version, int srv_version)
62{ 60{
63 int icframe_vercnt; 61 int icframe_major, icframe_minor;
64 int icmsg_vercnt; 62 int icmsg_major, icmsg_minor;
63 int fw_major, fw_minor;
64 int srv_major, srv_minor;
65 int i; 65 int i;
66 bool found_match = false;
66 67
67 icmsghdrp->icmsgsize = 0x10; 68 icmsghdrp->icmsgsize = 0x10;
69 fw_major = (fw_version >> 16);
70 fw_minor = (fw_version & 0xFFFF);
71
72 srv_major = (srv_version >> 16);
73 srv_minor = (srv_version & 0xFFFF);
68 74
69 negop = (struct icmsg_negotiate *)&buf[ 75 negop = (struct icmsg_negotiate *)&buf[
70 sizeof(struct vmbuspipe_hdr) + 76 sizeof(struct vmbuspipe_hdr) +
71 sizeof(struct icmsg_hdr)]; 77 sizeof(struct icmsg_hdr)];
72 78
73 icframe_vercnt = negop->icframe_vercnt; 79 icframe_major = negop->icframe_vercnt;
74 icmsg_vercnt = negop->icmsg_vercnt; 80 icframe_minor = 0;
81
82 icmsg_major = negop->icmsg_vercnt;
83 icmsg_minor = 0;
75 84
76 /* 85 /*
77 * Select the framework version number we will 86 * Select the framework version number we will
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
79 */ 88 */
80 89
81 for (i = 0; i < negop->icframe_vercnt; i++) { 90 for (i = 0; i < negop->icframe_vercnt; i++) {
82 if (negop->icversion_data[i].major <= max_fw_version) 91 if ((negop->icversion_data[i].major == fw_major) &&
83 icframe_vercnt = negop->icversion_data[i].major; 92 (negop->icversion_data[i].minor == fw_minor)) {
93 icframe_major = negop->icversion_data[i].major;
94 icframe_minor = negop->icversion_data[i].minor;
95 found_match = true;
96 }
84 } 97 }
85 98
99 if (!found_match)
100 goto fw_error;
101
102 found_match = false;
103
86 for (i = negop->icframe_vercnt; 104 for (i = negop->icframe_vercnt;
87 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { 105 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
88 if (negop->icversion_data[i].major <= max_srv_version) 106 if ((negop->icversion_data[i].major == srv_major) &&
89 icmsg_vercnt = negop->icversion_data[i].major; 107 (negop->icversion_data[i].minor == srv_minor)) {
108 icmsg_major = negop->icversion_data[i].major;
109 icmsg_minor = negop->icversion_data[i].minor;
110 found_match = true;
111 }
90 } 112 }
91 113
92 /* 114 /*
93 * Respond with the maximum framework and service 115 * Respond with the framework and service
94 * version numbers we can support. 116 * version numbers we can support.
95 */ 117 */
96 negop->icframe_vercnt = 1; 118
97 negop->icmsg_vercnt = 1; 119fw_error:
98 negop->icversion_data[0].major = icframe_vercnt; 120 if (!found_match) {
99 negop->icversion_data[0].minor = 0; 121 negop->icframe_vercnt = 0;
100 negop->icversion_data[1].major = icmsg_vercnt; 122 negop->icmsg_vercnt = 0;
101 negop->icversion_data[1].minor = 0; 123 } else {
124 negop->icframe_vercnt = 1;
125 negop->icmsg_vercnt = 1;
126 }
127
128 negop->icversion_data[0].major = icframe_major;
129 negop->icversion_data[0].minor = icframe_minor;
130 negop->icversion_data[1].major = icmsg_major;
131 negop->icversion_data[1].minor = icmsg_minor;
132 return found_match;
102} 133}
103 134
104EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); 135EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
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 @@
29#include <linux/hyperv.h> 29#include <linux/hyperv.h>
30 30
31 31
32/*
33 * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
34 */
35#define WIN7_SRV_MAJOR 3
36#define WIN7_SRV_MINOR 0
37#define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
38
39#define WIN8_SRV_MAJOR 4
40#define WIN8_SRV_MINOR 0
41#define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
32 42
33/* 43/*
34 * Global state maintained for transaction that is being processed. 44 * Global state maintained for transaction that is being processed.
@@ -593,8 +603,19 @@ void hv_kvp_onchannelcallback(void *context)
593 sizeof(struct vmbuspipe_hdr)]; 603 sizeof(struct vmbuspipe_hdr)];
594 604
595 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 605 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
606 /*
607 * We start with win8 version and if the host cannot
608 * support that we use the previous version.
609 */
610 if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
611 recv_buffer, UTIL_FW_MAJOR_MINOR,
612 WIN8_SRV_MAJOR_MINOR))
613 goto done;
614
596 vmbus_prep_negotiate_resp(icmsghdrp, negop, 615 vmbus_prep_negotiate_resp(icmsghdrp, negop,
597 recv_buffer, MAX_SRV_VER, MAX_SRV_VER); 616 recv_buffer, UTIL_FW_MAJOR_MINOR,
617 WIN7_SRV_MAJOR_MINOR);
618
598 } else { 619 } else {
599 kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ 620 kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
600 sizeof(struct vmbuspipe_hdr) + 621 sizeof(struct vmbuspipe_hdr) +
@@ -626,6 +647,7 @@ void hv_kvp_onchannelcallback(void *context)
626 return; 647 return;
627 648
628 } 649 }
650done:
629 651
630 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION 652 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
631 | ICMSGHDRFLAG_RESPONSE; 653 | ICMSGHDRFLAG_RESPONSE;
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 8ad5653ce447..e4572f3f2834 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -24,6 +24,10 @@
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/hyperv.h> 25#include <linux/hyperv.h>
26 26
27#define VSS_MAJOR 5
28#define VSS_MINOR 0
29#define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR)
30
27 31
28 32
29/* 33/*
@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context)
186 190
187 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 191 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
188 vmbus_prep_negotiate_resp(icmsghdrp, negop, 192 vmbus_prep_negotiate_resp(icmsghdrp, negop,
189 recv_buffer, MAX_SRV_VER, MAX_SRV_VER); 193 recv_buffer, UTIL_FW_MAJOR_MINOR,
190 /* 194 VSS_MAJOR_MINOR);
191 * We currently negotiate the highest number the
192 * host has presented. If this version is not
193 * atleast 5.0, reject.
194 */
195 negop = (struct icmsg_negotiate *)&recv_buffer[
196 sizeof(struct vmbuspipe_hdr) +
197 sizeof(struct icmsg_hdr)];
198
199 if (negop->icversion_data[1].major < 5)
200 negop->icframe_vercnt = 0;
201 } else { 195 } else {
202 vss_msg = (struct hv_vss_msg *)&recv_buffer[ 196 vss_msg = (struct hv_vss_msg *)&recv_buffer[
203 sizeof(struct vmbuspipe_hdr) + 197 sizeof(struct vmbuspipe_hdr) +
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 2f561c5dfe24..c16164d4a28b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -28,6 +28,18 @@
28#include <linux/reboot.h> 28#include <linux/reboot.h>
29#include <linux/hyperv.h> 29#include <linux/hyperv.h>
30 30
31#define SHUTDOWN_MAJOR 3
32#define SHUTDOWN_MINOR 0
33#define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR)
34
35#define TIMESYNCH_MAJOR 3
36#define TIMESYNCH_MINOR 0
37#define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR)
38
39#define HEARTBEAT_MAJOR 3
40#define HEARTBEAT_MINOR 0
41#define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR)
42
31static void shutdown_onchannelcallback(void *context); 43static void shutdown_onchannelcallback(void *context);
32static struct hv_util_service util_shutdown = { 44static struct hv_util_service util_shutdown = {
33 .util_cb = shutdown_onchannelcallback, 45 .util_cb = shutdown_onchannelcallback,
@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context)
87 99
88 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 100 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
89 vmbus_prep_negotiate_resp(icmsghdrp, negop, 101 vmbus_prep_negotiate_resp(icmsghdrp, negop,
90 shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); 102 shut_txf_buf, UTIL_FW_MAJOR_MINOR,
103 SHUTDOWN_MAJOR_MINOR);
91 } else { 104 } else {
92 shutdown_msg = 105 shutdown_msg =
93 (struct shutdown_msg_data *)&shut_txf_buf[ 106 (struct shutdown_msg_data *)&shut_txf_buf[
@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context)
213 226
214 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 227 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
215 vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, 228 vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
216 MAX_SRV_VER, MAX_SRV_VER); 229 UTIL_FW_MAJOR_MINOR,
230 TIMESYNCH_MAJOR_MINOR);
217 } else { 231 } else {
218 timedatap = (struct ictimesync_data *)&time_txf_buf[ 232 timedatap = (struct ictimesync_data *)&time_txf_buf[
219 sizeof(struct vmbuspipe_hdr) + 233 sizeof(struct vmbuspipe_hdr) +
@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context)
253 267
254 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 268 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
255 vmbus_prep_negotiate_resp(icmsghdrp, NULL, 269 vmbus_prep_negotiate_resp(icmsghdrp, NULL,
256 hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); 270 hbeat_txf_buf, UTIL_FW_MAJOR_MINOR,
271 HEARTBEAT_MAJOR_MINOR);
257 } else { 272 } else {
258 heartbeat_msg = 273 heartbeat_msg =
259 (struct heartbeat_msg_data *)&hbeat_txf_buf[ 274 (struct heartbeat_msg_data *)&hbeat_txf_buf[