aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2012-05-12 16:44:58 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-14 11:59:31 -0400
commitc836d0ab70acf7b7bd2b698278e8abae9e6d9978 (patch)
tree5e3c677b2314e6643785133569950d29cbf4dd7f /drivers/hv
parenta360530012766e5fd752bd6538c8cc6349846781 (diff)
Drivers: hv: util: Properly handle version negotiations.
The current version negotiation code is not "future proof". Fix this by allowing each service the flexibility to either specify the highest version it can support or it can support the highest version number the host is offering. 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')
-rw-r--r--drivers/hv/channel_mgmt.c54
-rw-r--r--drivers/hv/hv_kvp.c3
-rw-r--r--drivers/hv/hv_util.c9
3 files changed, 46 insertions, 20 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 6c8c4d340930..2b8b8d4558d2 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -46,37 +46,59 @@ struct vmbus_channel_message_table_entry {
46 * 46 *
47 * @icmsghdrp is of type &struct icmsg_hdr. 47 * @icmsghdrp is of type &struct icmsg_hdr.
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. This response can 49 * Set up and fill in default negotiate response message.
50 * come from both the vmbus driver and the hv_utils driver. The current api 50 *
51 * will respond properly to both Windows 2008 and Windows 2008-R2 operating 51 * The max_fw_version specifies the maximum framework version that
52 * systems. 52 * we can support and max _srv_version specifies the maximum service
53 * version we can support. A special value MAX_SRV_VER can be
54 * specified to indicate that we can handle the maximum version
55 * exposed by the host.
53 * 56 *
54 * Mainly used by Hyper-V drivers. 57 * Mainly used by Hyper-V drivers.
55 */ 58 */
56void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, 59void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
57 struct icmsg_negotiate *negop, u8 *buf) 60 struct icmsg_negotiate *negop, u8 *buf,
61 int max_fw_version, int max_srv_version)
58{ 62{
63 int icframe_vercnt;
64 int icmsg_vercnt;
65 int i;
66
59 icmsghdrp->icmsgsize = 0x10; 67 icmsghdrp->icmsgsize = 0x10;
60 68
61 negop = (struct icmsg_negotiate *)&buf[ 69 negop = (struct icmsg_negotiate *)&buf[
62 sizeof(struct vmbuspipe_hdr) + 70 sizeof(struct vmbuspipe_hdr) +
63 sizeof(struct icmsg_hdr)]; 71 sizeof(struct icmsg_hdr)];
64 72
65 if (negop->icframe_vercnt == 2 && 73 icframe_vercnt = negop->icframe_vercnt;
66 negop->icversion_data[1].major == 3) { 74 icmsg_vercnt = negop->icmsg_vercnt;
67 negop->icversion_data[0].major = 3; 75
68 negop->icversion_data[0].minor = 0; 76 /*
69 negop->icversion_data[1].major = 3; 77 * Select the framework version number we will
70 negop->icversion_data[1].minor = 0; 78 * support.
71 } else { 79 */
72 negop->icversion_data[0].major = 1; 80
73 negop->icversion_data[0].minor = 0; 81 for (i = 0; i < negop->icframe_vercnt; i++) {
74 negop->icversion_data[1].major = 1; 82 if (negop->icversion_data[i].major <= max_fw_version)
75 negop->icversion_data[1].minor = 0; 83 icframe_vercnt = negop->icversion_data[i].major;
84 }
85
86 for (i = negop->icframe_vercnt;
87 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
88 if (negop->icversion_data[i].major <= max_srv_version)
89 icmsg_vercnt = negop->icversion_data[i].major;
76 } 90 }
77 91
92 /*
93 * Respond with the maximum framework and service
94 * version numbers we can support.
95 */
78 negop->icframe_vercnt = 1; 96 negop->icframe_vercnt = 1;
79 negop->icmsg_vercnt = 1; 97 negop->icmsg_vercnt = 1;
98 negop->icversion_data[0].major = icframe_vercnt;
99 negop->icversion_data[0].minor = 0;
100 negop->icversion_data[1].major = icmsg_vercnt;
101 negop->icversion_data[1].minor = 0;
80} 102}
81 103
82EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); 104EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 6186025209ce..0012eed6d872 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -394,7 +394,8 @@ void hv_kvp_onchannelcallback(void *context)
394 sizeof(struct vmbuspipe_hdr)]; 394 sizeof(struct vmbuspipe_hdr)];
395 395
396 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 396 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
397 vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); 397 vmbus_prep_negotiate_resp(icmsghdrp, negop,
398 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
398 } else { 399 } else {
399 kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ 400 kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
400 sizeof(struct vmbuspipe_hdr) + 401 sizeof(struct vmbuspipe_hdr) +
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index dbb8b8eec210..d3ac6a40118b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -70,7 +70,8 @@ static void shutdown_onchannelcallback(void *context)
70 sizeof(struct vmbuspipe_hdr)]; 70 sizeof(struct vmbuspipe_hdr)];
71 71
72 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 72 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
73 vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); 73 vmbus_prep_negotiate_resp(icmsghdrp, negop,
74 shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
74 } else { 75 } else {
75 shutdown_msg = 76 shutdown_msg =
76 (struct shutdown_msg_data *)&shut_txf_buf[ 77 (struct shutdown_msg_data *)&shut_txf_buf[
@@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context)
195 sizeof(struct vmbuspipe_hdr)]; 196 sizeof(struct vmbuspipe_hdr)];
196 197
197 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 198 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
198 vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); 199 vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
200 MAX_SRV_VER, MAX_SRV_VER);
199 } else { 201 } else {
200 timedatap = (struct ictimesync_data *)&time_txf_buf[ 202 timedatap = (struct ictimesync_data *)&time_txf_buf[
201 sizeof(struct vmbuspipe_hdr) + 203 sizeof(struct vmbuspipe_hdr) +
@@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context)
234 sizeof(struct vmbuspipe_hdr)]; 236 sizeof(struct vmbuspipe_hdr)];
235 237
236 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 238 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
237 vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); 239 vmbus_prep_negotiate_resp(icmsghdrp, NULL,
240 hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
238 } else { 241 } else {
239 heartbeat_msg = 242 heartbeat_msg =
240 (struct heartbeat_msg_data *)&hbeat_txf_buf[ 243 (struct heartbeat_msg_data *)&hbeat_txf_buf[