Greg KH
2010-May-04 15:29 UTC
[PATCH 1/1] hv: Added new hv_utils driver with shutdown as first functionality - NO OUTLOOK
On Tue, May 04, 2010 at 03:55:05PM -0700, Hank Janssen wrote:> > Resending this patch from my personal Linux server. Exchange server and > outlook at Microsoft seems to badly munge my patch. :( > > From: Hank Janssen <hjanssen at sailtheuniverse.com>In the future, please put your microsoft email address here.> Subject: [PATCH 1/1] hv: Added new hv_utils driver with shutdown as first functionality > > Addition of new driver for Hyper-V called hv_utils. > This driver is intended to support things like KVP, Timesync, Heartbeat etc. > > This first release has support for Gracefull shutdown. > e.g. Select shutdown from the Hyper-V main admin screen and the Linux VM > will do a gracefull shutdown. > > Signed-off-by: Hank Janssen <microsoft.com>That's not a valid email address.> Signed-off-by: Hank Janssen <sailtheuniverse.com>Neither is that. Also, you "signed-off" on a patch twice, not good. Other than that, which I fixed up by hand, it looks good, and I've applied it and added some clean-up patches on top of it to resolve some issues. thanks, greg k-h
Hank Janssen
2010-May-04 22:55 UTC
[PATCH 1/1] hv: Added new hv_utils driver with shutdown as first functionality - NO OUTLOOK
Resending this patch from my personal Linux server. Exchange server and outlook at Microsoft seems to badly munge my patch. :( From: Hank Janssen <hjanssen at sailtheuniverse.com> Subject: [PATCH 1/1] hv: Added new hv_utils driver with shutdown as first functionality Addition of new driver for Hyper-V called hv_utils. This driver is intended to support things like KVP, Timesync, Heartbeat etc. This first release has support for Gracefull shutdown. e.g. Select shutdown from the Hyper-V main admin screen and the Linux VM will do a gracefull shutdown. Signed-off-by: Hank Janssen <microsoft.com> Signed-off-by: Hank Janssen <sailtheuniverse.com> Signed-off-by: Haiyang Zhang <haiyangz at microsoft.com> --- drivers/staging/hv/Channel.c | 34 ++++++- drivers/staging/hv/ChannelMgmt.c | 148 +++++++++++++++++++++++++++++++- drivers/staging/hv/Kconfig | 6 ++ drivers/staging/hv/Makefile | 2 + drivers/staging/hv/VmbusPacketFormat.h | 1 + drivers/staging/hv/ext_utils.c | 27 ++++++ drivers/staging/hv/hyperv_utils.c | 134 +++++++++++++++++++++++++++++ drivers/staging/hv/utils.h | 94 ++++++++++++++++++++ 8 files changed, 438 insertions(+), 8 deletions(-) create mode 100644 drivers/staging/hv/ext_utils.c create mode 100644 drivers/staging/hv/hyperv_utils.c create mode 100644 drivers/staging/hv/utils.h diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c index 328d3a0..de2ccb1 100644 --- a/drivers/staging/hv/Channel.c +++ b/drivers/staging/hv/Channel.c @@ -21,6 +21,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/module.h> #include "osd.h" #include "logging.h" #include "VmbusPrivate.h" @@ -666,8 +667,19 @@ void VmbusChannelClose(struct vmbus_channel *Channel) DPRINT_EXIT(VMBUS); } -/* - * VmbusChannelSendPacket - Send the specified buffer on the given channel +/** + * VmbusChannelSendPacket() - Send the specified buffer on the given channel + * @Channel: Pointer to vmbus_channel structure. + * @Buffer: Pointer to the buffer you want to receive the data into. + * @BufferLen: Maximum size of what the the buffer will hold + * @RequestId: Identifier of the request + * @vmbus_packet_type: Type of packet that is being send e.g. negotiate, time + * packet etc. + * + * Sends data in @Buffer directly to hyper-v via the vmbus + * This will send the data unparsed to hyper-v. + * + * Mainly used by Hyper-V drivers. */ int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer, u32 BufferLen, u64 RequestId, @@ -711,6 +723,7 @@ int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer, return ret; } +EXPORT_SYMBOL(VmbusChannelSendPacket); /* * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer @@ -848,10 +861,20 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel, return ret; } -/* - * VmbusChannelRecvPacket - Retrieve the user packet on the specified channel + +/** + * VmbusChannelRecvPacket() - Retrieve the user packet on the specified channel + * @Channel: Pointer to vmbus_channel structure. + * @Buffer: Pointer to the buffer you want to receive the data into. + * @BufferLen: Maximum size of what the the buffer will hold + * @BufferActualLen: The actual size of the data after it was received + * @RequestId: Identifier of the request + * + * Receives directly from the hyper-v vmbus and puts the data it received + * into Buffer. This will receive the data unparsed from hyper-v. + * + * Mainly used by Hyper-V drivers. */ -/* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */ int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer, u32 BufferLen, u32 *BufferActualLen, u64 *RequestId) { @@ -913,6 +936,7 @@ int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer, return 0; } +EXPORT_SYMBOL(VmbusChannelRecvPacket); /* * VmbusChannelRecvPacketRaw - Retrieve the raw packet on the specified channel diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c index 43f28f2..9c3069f 100644 --- a/drivers/staging/hv/ChannelMgmt.c +++ b/drivers/staging/hv/ChannelMgmt.c @@ -22,18 +22,22 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/list.h> +#include <linux/module.h> #include "osd.h" #include "logging.h" #include "VmbusPrivate.h" +#include "utils.h" struct vmbus_channel_message_table_entry { enum vmbus_channel_message_type messageType; void (*messageHandler)(struct vmbus_channel_message_header *msg); }; -#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 4 +#define MAX_MSG_TYPES 1 +#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 5 + static const struct hv_guid - gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { + gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ /* Storage - SCSI */ { @@ -69,8 +73,127 @@ static const struct hv_guid 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 } }, + /* 0E0B6031-5213-4934-818B-38D90CED39DB */ + /* Shutdown */ + { + .data = { + 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB + } + }, }; + +/** + * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message + * @icmsghdrp: Pointer to msg header structure + * @icmsg_negotiate: Pointer to negotiate message structure + * @buf: Raw buffer channel data + * + * @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. + * + * Mainly used by Hyper-V drivers. + */ +void 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; + } +} +EXPORT_SYMBOL(prep_negotiate_resp); + +/** + * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK + * Hyper-V requests + * @context: Pointer to argument structure. + * + * Set up the default handler for non device driver specific requests + * from Hyper-V. This stub responds to the default negotiate messages + * that come in for every non IDE/SCSI/Network request. + * This behavior is normally overwritten in the hv_utils driver. That + * driver handles requests like gracefull shutdown, heartbeats etc. + * + * Mainly used by Hyper-V drivers. + */ +void chn_cb_negotiate(void *context) +{ + struct vmbus_channel *channel = context; + u8 *buf; + u32 buflen, recvlen; + u64 requestid; + + struct icmsg_hdr *icmsghdrp; + struct icmsg_negotiate *negop = NULL; + + buflen = PAGE_SIZE; + buf = kmalloc(buflen, GFP_ATOMIC); + + VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid); + + if (recvlen > 0) { + icmsghdrp = (struct icmsg_hdr *)&buf[ + sizeof(struct vmbuspipe_hdr)]; + + prep_negotiate_resp(icmsghdrp, negop, buf); + + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION + | ICMSGHDRFLAG_RESPONSE; + + VmbusChannelSendPacket(channel, buf, + recvlen, requestid, + VmbusPacketTypeDataInBand, 0); + } + + kfree(buf); +} +EXPORT_SYMBOL(chn_cb_negotiate); + +/* + * Function table used for message responses for non IDE/SCSI/Network type + * messages. (Such as KVP/Shutdown etc) + */ +struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { + /* 0E0B6031-5213-4934-818B-38D90CED39DB */ + /* Shutdown */ + { + .msg_type = HV_SHUTDOWN_MSG, + .data = { + 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB + }, + .callback = chn_cb_negotiate, + .log_msg = "Shutdown channel functionality initialized" + }, +}; +EXPORT_SYMBOL(hv_cb_utils); + /* * AllocVmbusChannel - Allocate and initialize a vmbus channel object */ @@ -132,7 +255,8 @@ void FreeVmbusChannel(struct vmbus_channel *Channel) } /* - * VmbusChannelProcessOffer - Process the offer by creating a channel/device associated with this offer + * VmbusChannelProcessOffer - Process the offer by creating a channel/device + * associated with this offer */ static void VmbusChannelProcessOffer(void *context) { @@ -140,6 +264,7 @@ static void VmbusChannelProcessOffer(void *context) struct vmbus_channel *channel; bool fNew = true; int ret; + int cnt; unsigned long flags; DPRINT_ENTER(VMBUS); @@ -209,6 +334,23 @@ static void VmbusChannelProcessOffer(void *context) * can cleanup properly */ newChannel->State = CHANNEL_OPEN_STATE; + cnt = 0; + + while (cnt != MAX_MSG_TYPES) { + if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType, + &hv_cb_utils[cnt].data, + sizeof(struct hv_guid)) == 0) { + DPRINT_INFO(VMBUS, "%s", + hv_cb_utils[cnt].log_msg); + + if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, + 2 * PAGE_SIZE, NULL, 0, + hv_cb_utils[cnt].callback, + newChannel) == 0) + hv_cb_utils[cnt].channel = newChannel; + } + cnt++; + } } DPRINT_EXIT(VMBUS); } diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig index 4044702..79afb1e 100644 --- a/drivers/staging/hv/Kconfig +++ b/drivers/staging/hv/Kconfig @@ -29,4 +29,10 @@ config HYPERV_NET help Select this option to enable the Hyper-V virtual network driver. +config HYPERV_UTILS + tristate "Microsoft Hyper-V Utilities driver" + default HYPERV + help + Select this option to enable the Hyper-V Utilities. + endif diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile index 27ebae8..d2977ab 100644 --- a/drivers/staging/hv/Makefile +++ b/drivers/staging/hv/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_HYPERV) += hv_vmbus.o obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o obj-$(CONFIG_HYPERV_BLOCK) += hv_blkvsc.o obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o +obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o hv_vmbus-objs := vmbus_drv.o osd.o \ Vmbus.o Hv.o Connection.o Channel.o \ @@ -9,3 +10,4 @@ hv_vmbus-objs := vmbus_drv.o osd.o \ hv_storvsc-objs := storvsc_drv.o StorVsc.o hv_blkvsc-objs := blkvsc_drv.o BlkVsc.o hv_netvsc-objs := netvsc_drv.o NetVsc.o RndisFilter.o +hv_utils-objs := hyperv_utils.o ext_utils.o diff --git a/drivers/staging/hv/VmbusPacketFormat.h b/drivers/staging/hv/VmbusPacketFormat.h index 79120bc..f9f6b4b 100644 --- a/drivers/staging/hv/VmbusPacketFormat.h +++ b/drivers/staging/hv/VmbusPacketFormat.h @@ -22,6 +22,7 @@ */ #ifndef _VMBUSPACKETFORMAT_H_ +#define _VMBUSPACKETFORMAT_H_ struct vmpacket_descriptor { u16 Type; diff --git a/drivers/staging/hv/ext_utils.c b/drivers/staging/hv/ext_utils.c new file mode 100644 index 0000000..a44cd1b --- /dev/null +++ b/drivers/staging/hv/ext_utils.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010, Microsoft Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Authors: + * Haiyang Zhang <haiyangz at microsoft.com> + * Hank Janssen <hjanssen at microsoft.com> + */ +#include <linux/reboot.h> +#include "utils.h" + +void shutdown_linux_system() +{ + orderly_poweroff(false); +} diff --git a/drivers/staging/hv/hyperv_utils.c b/drivers/staging/hv/hyperv_utils.c new file mode 100644 index 0000000..2a48647 --- /dev/null +++ b/drivers/staging/hv/hyperv_utils.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010, Microsoft Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Authors: + * Haiyang Zhang <haiyangz at microsoft.com> + * Hank Janssen <hjanssen at microsoft.com> + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/sysctl.h> +#include <linux/version.h> + +#include "logging.h" +#include "osd.h" +#include "vmbus.h" +#include "VmbusPacketFormat.h" +#include "VmbusChannelInterface.h" +#include "VersionInfo.h" +#include "Channel.h" +#include "VmbusPrivate.h" +#include "VmbusApi.h" +#include "utils.h" + + +void shutdown_onchannelcallback(void *context) +{ + struct vmbus_channel *channel = context; + u8 *buf; + u32 buflen, recvlen; + u64 requestid; + u8 execute_shutdown = false; + + struct shutdown_msg_data *shutdown_msg; + + struct icmsg_hdr *icmsghdrp; + struct icmsg_negotiate *negop = NULL; + + DPRINT_ENTER(VMBUS); + + buflen = PAGE_SIZE; + buf = kmalloc(buflen, GFP_ATOMIC); + + VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid); + + if (recvlen > 0) { + DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld", + recvlen, requestid); + + icmsghdrp = (struct icmsg_hdr *)&buf[ + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { + prep_negotiate_resp(icmsghdrp, negop, buf); + } else { + shutdown_msg = (struct shutdown_msg_data *)&buf[ + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + + switch (shutdown_msg->flags) { + case 0: + case 1: + icmsghdrp->status = HV_S_OK; + execute_shutdown = true; + + DPRINT_INFO(VMBUS, "Shutdown request received -" + " gracefull shutdown initiated"); + break; + default: + icmsghdrp->status = HV_E_FAIL; + execute_shutdown = false; + + DPRINT_INFO(VMBUS, "Shutdown request received -" + " Invalid request"); + break; + }; + } + + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION + | ICMSGHDRFLAG_RESPONSE; + + VmbusChannelSendPacket(channel, buf, + recvlen, requestid, + VmbusPacketTypeDataInBand, 0); + } + + kfree(buf); + + DPRINT_EXIT(VMBUS); + + if (execute_shutdown == true) + shutdown_linux_system(); +} + +static int __init init_hyperv_utils(void) +{ + printk(KERN_INFO "Registering HyperV Utility Driver\n"); + + hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback + &shutdown_onchannelcallback; + hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; + + return 0; +} + +static void exit_hyperv_utils(void) +{ + printk(KERN_INFO "De-Registered HyperV Utility Driver\n"); + + hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback + &chn_cb_negotiate; + hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate; +} + +module_init(init_hyperv_utils); +module_exit(exit_hyperv_utils); + +MODULE_DESCRIPTION("Hyper-V Utilities"); +MODULE_VERSION(HV_DRV_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h new file mode 100644 index 0000000..4e09804 --- /dev/null +++ b/drivers/staging/hv/utils.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2009, Microsoft Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Authors: + * Haiyang Zhang <haiyangz at microsoft.com> + * Hank Janssen <hjanssen at microsoft.com> + */ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +/* + * Common header for Hyper-V ICs + */ +#define ICMSGTYPE_NEGOTIATE 0 +#define ICMSGTYPE_HEARTBEAT 1 +#define ICMSGTYPE_KVPEXCHANGE 2 +#define ICMSGTYPE_SHUTDOWN 3 +#define ICMSGTYPE_TIMESYNC 4 +#define ICMSGTYPE_VSS 5 + +#define ICMSGHDRFLAG_TRANSACTION 1 +#define ICMSGHDRFLAG_REQUEST 2 +#define ICMSGHDRFLAG_RESPONSE 4 + +#define HV_S_OK 0x00000000 +#define HV_E_FAIL 0x80004005 +#define HV_ERROR_NOT_SUPPORTED 0x80070032 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7 + +struct vmbuspipe_hdr { + u32 flags; + u32 msgsize; +} __attribute__((packed)); + +struct ic_version { + u16 major; + u16 minor; +} __attribute__((packed)); + +struct icmsg_hdr { + struct ic_version icverframe; + u16 icmsgtype; + struct ic_version icvermsg; + u16 icmsgsize; + u32 status; + u8 ictransaction_id; + u8 icflags; + u8 reserved[2]; +} __attribute__((packed)); + +struct icmsg_negotiate { + u16 icframe_vercnt; + u16 icmsg_vercnt; + u32 reserved; + struct ic_version icversion_data[1]; /* any size array */ +} __attribute__((packed)); + +struct shutdown_msg_data { + u32 reason_code; + u32 timeout_seconds; + u32 flags; + u8 display_message[2048]; +} __attribute__((packed)); + +#define HV_SHUTDOWN_MSG 0 + +struct hyperv_service_callback { + u8 msg_type; + char *log_msg; + unsigned char data[16]; + struct vmbus_channel *channel; + void (*callback) (void *context); +}; + +extern void prep_negotiate_resp(struct icmsg_hdr *, + struct icmsg_negotiate *, u8 *); +extern void shutdown_linux_system(void); +extern void chn_cb_negotiate(void *); +extern struct hyperv_service_callback hv_cb_utils[]; + +#endif /* _UTILS_H_ */ -- 1.6.0.2
Hank Janssen
2010-May-15 21:39 UTC
[PATCH 1/1] staging: hv: Added heartbeat functionality to hv_utils
From: Hank Janssen <hjanssen at microsoft.com> Subject: [PATCH 1/1] staging: hv: Added heartbeat functionality to hv_utils Add heartbeat functionality to hv_utils/Hyper-V Signed-off-by: Haiyang Zhang <haiyangz at microsoft.com> Signed-off-by: Hank Janssen <hjanssen at microsoft.com> --- drivers/staging/hv/channel_mgmt.c | 23 ++++++++++++- drivers/staging/hv/hv_utils.c | 64 +++++++++++++++++++++++++++++++++++++ drivers/staging/hv/utils.h | 5 +++ drivers/staging/hv/version_info.h | 3 +- 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 6877e8e..3f53b4d 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -33,8 +33,8 @@ struct vmbus_channel_message_table_entry { void (*messageHandler)(struct vmbus_channel_message_header *msg); }; -#define MAX_MSG_TYPES 2 -#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 6 +#define MAX_MSG_TYPES 3 +#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 7 static const struct hv_guid gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { @@ -89,6 +89,14 @@ static const struct hv_guid 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } }, + /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ + /* Heartbeat */ + { + .data = { + 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d + } + }, }; @@ -211,6 +219,17 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { .callback = chn_cb_negotiate, .log_msg = "Timesync channel functionality initialized" }, + /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ + /* Heartbeat */ + { + .msg_type = HV_HEARTBEAT_MSG, + .data = { + 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d + }, + .callback = chn_cb_negotiate, + .log_msg = "Heartbeat channel functionality initialized" + }, }; EXPORT_SYMBOL(hv_cb_utils); diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c index db45d97..8a49aaf 100644 --- a/drivers/staging/hv/hv_utils.c +++ b/drivers/staging/hv/hv_utils.c @@ -194,6 +194,62 @@ static void timesync_onchannelcallback(void *context) DPRINT_EXIT(VMBUS); } +/* + * Heartbeat functionality. + * Every two seconds, Hyper-V send us a heartbeat request message. + * we respond to this message, and Hyper-V knows we are alive. + */ +static void heartbeat_onchannelcallback(void *context) +{ + struct vmbus_channel *channel = context; + u8 *buf; + u32 buflen, recvlen; + u64 requestid; + struct icmsg_hdr *icmsghdrp; + struct heartbeat_msg_data *heartbeat_msg; + + DPRINT_ENTER(VMBUS); + + buflen = PAGE_SIZE; + buf = kmalloc(buflen, GFP_ATOMIC); + + VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid); + + if (recvlen > 0) { + DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld", + recvlen, requestid); + + icmsghdrp = (struct icmsg_hdr *)&buf[ + sizeof(struct vmbuspipe_hdr)]; + + icmsghdrp = (struct icmsg_hdr *)&buf[ + sizeof(struct vmbuspipe_hdr)]; + + if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { + prep_negotiate_resp(icmsghdrp, NULL, buf); + } else { + heartbeat_msg = (struct heartbeat_msg_data *)&buf[ + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + + DPRINT_DBG(VMBUS, "heartbeat seq = %lld", + heartbeat_msg->seq_num); + + heartbeat_msg->seq_num += 1; + } + + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION + | ICMSGHDRFLAG_RESPONSE; + + VmbusChannelSendPacket(channel, buf, + recvlen, requestid, + VmbusPacketTypeDataInBand, 0); + } + + kfree(buf); + + DPRINT_EXIT(VMBUS); +} static int __init init_hyperv_utils(void) { @@ -207,6 +263,10 @@ static int __init init_hyperv_utils(void) ×ync_onchannelcallback; hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback; + hv_cb_utils[HV_HEARTBEAT_MSG].channel->OnChannelCallback + &heartbeat_onchannelcallback; + hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback; + return 0; } @@ -221,6 +281,10 @@ static void exit_hyperv_utils(void) hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback &chn_cb_negotiate; hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate; + + hv_cb_utils[HV_HEARTBEAT_MSG].channel->OnChannelCallback + &chn_cb_negotiate; + hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate; } module_init(init_hyperv_utils); diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h index a4b9fd0..7c07499 100644 --- a/drivers/staging/hv/utils.h +++ b/drivers/staging/hv/utils.h @@ -75,6 +75,10 @@ struct shutdown_msg_data { u8 display_message[2048]; } __attribute__((packed)); +struct heartbeat_msg_data { + u64 seq_num; + u32 reserved[8]; +} __attribute__((packed)); /* Time Sync IC defs */ #define ICTIMESYNCFLAG_PROBE 0 @@ -97,6 +101,7 @@ struct ictimesync_data{ /* Index for each IC struct in array hv_cb_utils[] */ #define HV_SHUTDOWN_MSG 0 #define HV_TIMESYNC_MSG 1 +#define HV_HEARTBEAT_MSG 2 struct hyperv_service_callback { u8 msg_type; diff --git a/drivers/staging/hv/version_info.h b/drivers/staging/hv/version_info.h index 82e74b1..35178f2 100644 --- a/drivers/staging/hv/version_info.h +++ b/drivers/staging/hv/version_info.h @@ -40,8 +40,9 @@ * Minor Number Changes when new functionality is added * to the Linux IC's that is not a bug fix. * + * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync */ -#define HV_DRV_VERSION "3.0" +#define HV_DRV_VERSION "3.1" #endif -- 1.6.0.2
Seemingly Similar Threads
- [PATCH 1/1] hv: Added new hv_utils driver with shutdown as first functionality - NO OUTLOOK
- [PATCH 1/1] hv: Added new hv_utils driver to hyper-v
- [PATCH 1/1] hv: Added new hv_utils driver to hyper-v
- [PATCH 1/1] hv: Use only one receive buffer per channel and kmalloc on initialize
- [PATCH 1/1] hv: Use only one receive buffer per channel and kmalloc on initialize