From 415f0a02adaea754dc85cde7b50707f7fbc4cf3f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 28 Mar 2012 09:58:07 +0300 Subject: hv: fix return type of hv_post_message() This function returns negative error codes, but because the type is u16 they get truncated into positive numbers. It doesn't look like the callers care, but we should fix it anyway as a cleanup. Signed-off-by: Dan Carpenter Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv.c | 2 +- drivers/hv/hyperv_vmbus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hv') diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 15956bd48b48..86f8885aeb45 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -252,7 +252,7 @@ void hv_cleanup(void) * * This involves a hypercall. */ -u16 hv_post_message(union hv_connection_id connection_id, +int hv_post_message(union hv_connection_id connection_id, enum hv_message_type message_type, void *payload, size_t payload_size) { diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 699f0d8e59ed..b9426a6592ee 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -495,7 +495,7 @@ extern int hv_init(void); extern void hv_cleanup(void); -extern u16 hv_post_message(union hv_connection_id connection_id, +extern int hv_post_message(union hv_connection_id connection_id, enum hv_message_type message_type, void *payload, size_t payload_size); -- cgit v1.2.3 From a360530012766e5fd752bd6538c8cc6349846781 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 12 May 2012 13:44:57 -0700 Subject: Drivers: hv: Get rid of an unnecessary check in vmbus_prep_negotiate_resp() The vmbus_prep_negotiate_resp() is only invoked when we are negotiating the version; so the current check in vmbus_prep_negotiate_resp() is unnecessary. Get rid of it. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel_mgmt.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers/hv') diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 9ffbfc575a0c..6c8c4d340930 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -56,30 +56,29 @@ struct vmbus_channel_message_table_entry { void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, struct icmsg_negotiate *negop, u8 *buf) { - if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - icmsghdrp->icmsgsize = 0x10; - - negop = (struct icmsg_negotiate *)&buf[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - if (negop->icframe_vercnt == 2 && - negop->icversion_data[1].major == 3) { - negop->icversion_data[0].major = 3; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 3; - negop->icversion_data[1].minor = 0; - } else { - negop->icversion_data[0].major = 1; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 1; - negop->icversion_data[1].minor = 0; - } - - negop->icframe_vercnt = 1; - negop->icmsg_vercnt = 1; + icmsghdrp->icmsgsize = 0x10; + + negop = (struct icmsg_negotiate *)&buf[ + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + + if (negop->icframe_vercnt == 2 && + negop->icversion_data[1].major == 3) { + negop->icversion_data[0].major = 3; + negop->icversion_data[0].minor = 0; + negop->icversion_data[1].major = 3; + negop->icversion_data[1].minor = 0; + } else { + negop->icversion_data[0].major = 1; + negop->icversion_data[0].minor = 0; + negop->icversion_data[1].major = 1; + negop->icversion_data[1].minor = 0; } + + negop->icframe_vercnt = 1; + negop->icmsg_vercnt = 1; } + EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); /* -- cgit v1.2.3 From c836d0ab70acf7b7bd2b698278e8abae9e6d9978 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 12 May 2012 13:44:58 -0700 Subject: 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 Reviewed-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel_mgmt.c | 54 +++++++++++++++++++++++++++++++++-------------- drivers/hv/hv_kvp.c | 3 ++- drivers/hv/hv_util.c | 9 +++++--- include/linux/hyperv.h | 4 +++- 4 files changed, 49 insertions(+), 21 deletions(-) (limited to 'drivers/hv') 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 { * * @icmsghdrp is of type &struct icmsg_hdr. * @negop is of type &struct icmsg_negotiate. - * Set up and fill in default negotiate response message. This response can - * come from both the vmbus driver and the hv_utils driver. The current api - * will respond properly to both Windows 2008 and Windows 2008-R2 operating - * systems. + * Set up and fill in default negotiate response message. + * + * The max_fw_version specifies the maximum framework version that + * we can support and max _srv_version specifies the maximum service + * version we can support. A special value MAX_SRV_VER can be + * specified to indicate that we can handle the maximum version + * exposed by the host. * * Mainly used by Hyper-V drivers. */ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, - struct icmsg_negotiate *negop, u8 *buf) + struct icmsg_negotiate *negop, u8 *buf, + int max_fw_version, int max_srv_version) { + int icframe_vercnt; + int icmsg_vercnt; + int i; + icmsghdrp->icmsgsize = 0x10; negop = (struct icmsg_negotiate *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; - if (negop->icframe_vercnt == 2 && - negop->icversion_data[1].major == 3) { - negop->icversion_data[0].major = 3; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 3; - negop->icversion_data[1].minor = 0; - } else { - negop->icversion_data[0].major = 1; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = 1; - negop->icversion_data[1].minor = 0; + icframe_vercnt = negop->icframe_vercnt; + icmsg_vercnt = negop->icmsg_vercnt; + + /* + * Select the framework version number we will + * support. + */ + + for (i = 0; i < negop->icframe_vercnt; i++) { + if (negop->icversion_data[i].major <= max_fw_version) + icframe_vercnt = negop->icversion_data[i].major; + } + + for (i = negop->icframe_vercnt; + (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { + if (negop->icversion_data[i].major <= max_srv_version) + icmsg_vercnt = negop->icversion_data[i].major; } + /* + * Respond with the maximum framework and service + * version numbers we can support. + */ negop->icframe_vercnt = 1; negop->icmsg_vercnt = 1; + negop->icversion_data[0].major = icframe_vercnt; + negop->icversion_data[0].minor = 0; + negop->icversion_data[1].major = icmsg_vercnt; + negop->icversion_data[1].minor = 0; } EXPORT_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) sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); + vmbus_prep_negotiate_resp(icmsghdrp, negop, + recv_buffer, MAX_SRV_VER, MAX_SRV_VER); } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ 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) sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); + vmbus_prep_negotiate_resp(icmsghdrp, negop, + shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); } else { shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ @@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context) sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); + vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, + MAX_SRV_VER, MAX_SRV_VER); } else { timedatap = (struct ictimesync_data *)&time_txf_buf[ sizeof(struct vmbuspipe_hdr) + @@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context) sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { - vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); + vmbus_prep_negotiate_resp(icmsghdrp, NULL, + hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); } else { heartbeat_msg = (struct heartbeat_msg_data *)&hbeat_txf_buf[ diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 5852545e6bba..22172bd43745 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1035,8 +1035,10 @@ struct hyperv_service_callback { void (*callback) (void *context); }; +#define MAX_SRV_VER 0x7ffffff extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, - struct icmsg_negotiate *, u8 *); + struct icmsg_negotiate *, u8 *, int, + int); int hv_kvp_init(struct hv_util_service *); void hv_kvp_deinit(void); -- cgit v1.2.3