From: Dexuan Cui <decui@xxxxxxxxxxxxx> Sent: Saturday, January 25, 2020 11:54 AM > > The hv_utils driver currently supports a "shutdown" operation initiated > from the Hyper-V host. Newer versions of Hyper-V also support a "restart" > operation. So add support for the updated protocol version that has > "restart" support, and perform a clean reboot when such a message is > received from Hyper-V. > > To test the restart functionality, run this PowerShell command on the > Hyper-V host: > > Restart-VM <vmname> -Type Reboot > > Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx> > > --- > Changes in v2: > It's the same as v1. > > Changes in v3 (I addressed Michael's comments): > Used a better version of changelog from Michael. > Added a comment about the meaning of shutdown_msg->flags. > Call schedule_work() at the end of the function for consistency. > > drivers/hv/hv_util.c | 32 +++++++++++++++++++++++++++++++- > 1 file changed, 31 insertions(+), 1 deletion(-) > > diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c > index 766bd8457346..d815bea0fda3 100644 > --- a/drivers/hv/hv_util.c > +++ b/drivers/hv/hv_util.c > @@ -24,6 +24,8 @@ > > #define SD_MAJOR 3 > #define SD_MINOR 0 > +#define SD_MINOR_1 1 > +#define SD_VERSION_3_1 (SD_MAJOR << 16 | SD_MINOR_1) > #define SD_VERSION (SD_MAJOR << 16 | SD_MINOR) > > #define SD_MAJOR_1 1 > @@ -50,8 +52,9 @@ static int sd_srv_version; > static int ts_srv_version; > static int hb_srv_version; > > -#define SD_VER_COUNT 2 > +#define SD_VER_COUNT 3 > static const int sd_versions[] = { > + SD_VERSION_3_1, > SD_VERSION, > SD_VERSION_1 > }; > @@ -118,17 +121,28 @@ static void perform_shutdown(struct work_struct *dummy) > orderly_poweroff(true); > } > > +static void perform_restart(struct work_struct *dummy) > +{ > + orderly_reboot(); > +} > + > /* > * Perform the shutdown operation in a thread context. > */ > static DECLARE_WORK(shutdown_work, perform_shutdown); > > +/* > + * Perform the restart operation in a thread context. > + */ > +static DECLARE_WORK(restart_work, perform_restart); > + > static void shutdown_onchannelcallback(void *context) > { > struct vmbus_channel *channel = context; > u32 recvlen; > u64 requestid; > bool execute_shutdown = false; > + bool execute_reboot = false; > u8 *shut_txf_buf = util_shutdown.recv_buffer; > > struct shutdown_msg_data *shutdown_msg; > @@ -157,6 +171,12 @@ static void shutdown_onchannelcallback(void *context) > sizeof(struct vmbuspipe_hdr) + > sizeof(struct icmsg_hdr)]; > > + /* > + * shutdown_msg->flags can be 0 (shut down), 2(reboot), > + * or 4(hibernate). It may bitwise-OR 1, which means > + * performing the request by force. Linux always tries > + * to perform the request by force. > + */ > switch (shutdown_msg->flags) { > case 0: > case 1: > @@ -166,6 +186,14 @@ static void shutdown_onchannelcallback(void *context) > pr_info("Shutdown request received -" > " graceful shutdown initiated\n"); > break; > + case 2: > + case 3: > + icmsghdrp->status = HV_S_OK; > + execute_reboot = true; > + > + pr_info("Restart request received -" > + " graceful restart initiated\n"); > + break; > default: > icmsghdrp->status = HV_E_FAIL; > execute_shutdown = false; > @@ -186,6 +214,8 @@ static void shutdown_onchannelcallback(void *context) > > if (execute_shutdown == true) > schedule_work(&shutdown_work); > + if (execute_reboot == true) > + schedule_work(&restart_work); This works, and responds to my comment. But FWIW, a more compact approach would be to drop the boolean execute_shutdown, execute_restart, etc. local variables and have just this local variable: struct work_struct *work_to_do = NULL; In the "case" branches do: work_to_do = &shutdown_work; or work_to_do = &restart_work; Then at the bottom of the function, just do: if (work_to_do) schedule_work(work_to_do); Patch 3 of this series would then be a little simpler as well. > } > > /* > -- > 2.19.1