Skip to content

Commit c836d0a

Browse files
kattisrinivasangregkh
authored andcommitted
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 <[email protected]> Reviewed-by: Haiyang Zhang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a360530 commit c836d0a

File tree

4 files changed

+49
-21
lines changed

4 files changed

+49
-21
lines changed

drivers/hv/channel_mgmt.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,37 +46,59 @@ struct vmbus_channel_message_table_entry {
4646
*
4747
* @icmsghdrp is of type &struct icmsg_hdr.
4848
* @negop is of type &struct icmsg_negotiate.
49-
* Set up and fill in default negotiate response message. This response can
50-
* come from both the vmbus driver and the hv_utils driver. The current api
51-
* will respond properly to both Windows 2008 and Windows 2008-R2 operating
52-
* systems.
49+
* Set up and fill in default negotiate response message.
50+
*
51+
* The max_fw_version specifies the maximum framework version that
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.
5356
*
5457
* Mainly used by Hyper-V drivers.
5558
*/
5659
void 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)
5862
{
63+
int icframe_vercnt;
64+
int icmsg_vercnt;
65+
int i;
66+
5967
icmsghdrp->icmsgsize = 0x10;
6068

6169
negop = (struct icmsg_negotiate *)&buf[
6270
sizeof(struct vmbuspipe_hdr) +
6371
sizeof(struct icmsg_hdr)];
6472

65-
if (negop->icframe_vercnt == 2 &&
66-
negop->icversion_data[1].major == 3) {
67-
negop->icversion_data[0].major = 3;
68-
negop->icversion_data[0].minor = 0;
69-
negop->icversion_data[1].major = 3;
70-
negop->icversion_data[1].minor = 0;
71-
} else {
72-
negop->icversion_data[0].major = 1;
73-
negop->icversion_data[0].minor = 0;
74-
negop->icversion_data[1].major = 1;
75-
negop->icversion_data[1].minor = 0;
73+
icframe_vercnt = negop->icframe_vercnt;
74+
icmsg_vercnt = negop->icmsg_vercnt;
75+
76+
/*
77+
* Select the framework version number we will
78+
* support.
79+
*/
80+
81+
for (i = 0; i < negop->icframe_vercnt; i++) {
82+
if (negop->icversion_data[i].major <= max_fw_version)
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;
7690
}
7791

92+
/*
93+
* Respond with the maximum framework and service
94+
* version numbers we can support.
95+
*/
7896
negop->icframe_vercnt = 1;
7997
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;
80102
}
81103

82104
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);

drivers/hv/hv_kvp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,8 @@ void hv_kvp_onchannelcallback(void *context)
394394
sizeof(struct vmbuspipe_hdr)];
395395

396396
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);
398399
} else {
399400
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
400401
sizeof(struct vmbuspipe_hdr) +

drivers/hv/hv_util.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ static void shutdown_onchannelcallback(void *context)
7070
sizeof(struct vmbuspipe_hdr)];
7171

7272
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);
7475
} else {
7576
shutdown_msg =
7677
(struct shutdown_msg_data *)&shut_txf_buf[
@@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context)
195196
sizeof(struct vmbuspipe_hdr)];
196197

197198
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);
199201
} else {
200202
timedatap = (struct ictimesync_data *)&time_txf_buf[
201203
sizeof(struct vmbuspipe_hdr) +
@@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context)
234236
sizeof(struct vmbuspipe_hdr)];
235237

236238
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);
238241
} else {
239242
heartbeat_msg =
240243
(struct heartbeat_msg_data *)&hbeat_txf_buf[

include/linux/hyperv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,8 +1035,10 @@ struct hyperv_service_callback {
10351035
void (*callback) (void *context);
10361036
};
10371037

1038+
#define MAX_SRV_VER 0x7ffffff
10381039
extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *,
1039-
struct icmsg_negotiate *, u8 *);
1040+
struct icmsg_negotiate *, u8 *, int,
1041+
int);
10401042

10411043
int hv_kvp_init(struct hv_util_service *);
10421044
void hv_kvp_deinit(void);

0 commit comments

Comments
 (0)