Skip to content

Commit d0fa925

Browse files
committed
Merge tag 'hyperv-next-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull Hyper-V updates from Sasha Levin: - Most of the commits here are work to enable host-initiated hibernation support by Dexuan Cui. - Fix for a warning shown when host sends non-aligned balloon requests by Tianyu Lan. * tag 'hyperv-next-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: hv_utils: Add the support of hibernation hv_utils: Support host-initiated hibernation request hv_utils: Support host-initiated restart request Tools: hv: Reopen the devices if read() or write() returns errors video: hyperv: hyperv_fb: Use physical memory for fb on HyperV Gen 1 VMs. Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23) video: hyperv_fb: Fix hibernation for the deferred IO feature Input: hyperv-keyboard: Add the support of hibernation hv_balloon: Balloon up according to request page number
2 parents 46d6b7b + 54e19d3 commit d0fa925

File tree

15 files changed

+574
-108
lines changed

15 files changed

+574
-108
lines changed

drivers/hv/channel_mgmt.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,8 @@ channel_message_table[CHANNELMSG_COUNT] = {
13511351
{ CHANNELMSG_19, 0, NULL },
13521352
{ CHANNELMSG_20, 0, NULL },
13531353
{ CHANNELMSG_TL_CONNECT_REQUEST, 0, NULL },
1354+
{ CHANNELMSG_22, 0, NULL },
1355+
{ CHANNELMSG_TL_CONNECT_RESULT, 0, NULL },
13541356
};
13551357

13561358
/*
@@ -1362,25 +1364,16 @@ void vmbus_onmessage(void *context)
13621364
{
13631365
struct hv_message *msg = context;
13641366
struct vmbus_channel_message_header *hdr;
1365-
int size;
13661367

13671368
hdr = (struct vmbus_channel_message_header *)msg->u.payload;
1368-
size = msg->header.payload_size;
13691369

13701370
trace_vmbus_on_message(hdr);
13711371

1372-
if (hdr->msgtype >= CHANNELMSG_COUNT) {
1373-
pr_err("Received invalid channel message type %d size %d\n",
1374-
hdr->msgtype, size);
1375-
print_hex_dump_bytes("", DUMP_PREFIX_NONE,
1376-
(unsigned char *)msg->u.payload, size);
1377-
return;
1378-
}
1379-
1380-
if (channel_message_table[hdr->msgtype].message_handler)
1381-
channel_message_table[hdr->msgtype].message_handler(hdr);
1382-
else
1383-
pr_err("Unhandled channel message type %d\n", hdr->msgtype);
1372+
/*
1373+
* vmbus_on_msg_dpc() makes sure the hdr->msgtype here can not go
1374+
* out of bound and the message_handler pointer can not be NULL.
1375+
*/
1376+
channel_message_table[hdr->msgtype].message_handler(hdr);
13841377
}
13851378

13861379
/*

drivers/hv/hv_balloon.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,10 +1217,7 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
12171217
unsigned int i, j;
12181218
struct page *pg;
12191219

1220-
if (num_pages < alloc_unit)
1221-
return 0;
1222-
1223-
for (i = 0; (i * alloc_unit) < num_pages; i++) {
1220+
for (i = 0; i < num_pages / alloc_unit; i++) {
12241221
if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) >
12251222
HV_HYP_PAGE_SIZE)
12261223
return i * alloc_unit;
@@ -1258,7 +1255,7 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
12581255

12591256
}
12601257

1261-
return num_pages;
1258+
return i * alloc_unit;
12621259
}
12631260

12641261
static void balloon_up(struct work_struct *dummy)
@@ -1273,9 +1270,6 @@ static void balloon_up(struct work_struct *dummy)
12731270
long avail_pages;
12741271
unsigned long floor;
12751272

1276-
/* The host balloons pages in 2M granularity. */
1277-
WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0);
1278-
12791273
/*
12801274
* We will attempt 2M allocations. However, if we fail to
12811275
* allocate 2M chunks, we will go back to PAGE_SIZE allocations.
@@ -1285,14 +1279,13 @@ static void balloon_up(struct work_struct *dummy)
12851279
avail_pages = si_mem_available();
12861280
floor = compute_balloon_floor();
12871281

1288-
/* Refuse to balloon below the floor, keep the 2M granularity. */
1282+
/* Refuse to balloon below the floor. */
12891283
if (avail_pages < num_pages || avail_pages - num_pages < floor) {
12901284
pr_warn("Balloon request will be partially fulfilled. %s\n",
12911285
avail_pages < num_pages ? "Not enough memory." :
12921286
"Balloon floor reached.");
12931287

12941288
num_pages = avail_pages > floor ? (avail_pages - floor) : 0;
1295-
num_pages -= num_pages % PAGES_IN_2M;
12961289
}
12971290

12981291
while (!done) {

drivers/hv/hv_fcopy.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,61 @@ int hv_fcopy_init(struct hv_util_service *srv)
346346
return 0;
347347
}
348348

349+
static void hv_fcopy_cancel_work(void)
350+
{
351+
cancel_delayed_work_sync(&fcopy_timeout_work);
352+
cancel_work_sync(&fcopy_send_work);
353+
}
354+
355+
int hv_fcopy_pre_suspend(void)
356+
{
357+
struct vmbus_channel *channel = fcopy_transaction.recv_channel;
358+
struct hv_fcopy_hdr *fcopy_msg;
359+
360+
/*
361+
* Fake a CANCEL_FCOPY message for the user space daemon in case the
362+
* daemon is in the middle of copying some file. It doesn't matter if
363+
* there is already a message pending to be delivered to the user
364+
* space since we force fcopy_transaction.state to be HVUTIL_READY, so
365+
* the user space daemon's write() will fail with EINVAL (see
366+
* fcopy_on_msg()), and the daemon will reset the device by closing
367+
* and re-opening it.
368+
*/
369+
fcopy_msg = kzalloc(sizeof(*fcopy_msg), GFP_KERNEL);
370+
if (!fcopy_msg)
371+
return -ENOMEM;
372+
373+
tasklet_disable(&channel->callback_event);
374+
375+
fcopy_msg->operation = CANCEL_FCOPY;
376+
377+
hv_fcopy_cancel_work();
378+
379+
/* We don't care about the return value. */
380+
hvutil_transport_send(hvt, fcopy_msg, sizeof(*fcopy_msg), NULL);
381+
382+
kfree(fcopy_msg);
383+
384+
fcopy_transaction.state = HVUTIL_READY;
385+
386+
/* tasklet_enable() will be called in hv_fcopy_pre_resume(). */
387+
return 0;
388+
}
389+
390+
int hv_fcopy_pre_resume(void)
391+
{
392+
struct vmbus_channel *channel = fcopy_transaction.recv_channel;
393+
394+
tasklet_enable(&channel->callback_event);
395+
396+
return 0;
397+
}
398+
349399
void hv_fcopy_deinit(void)
350400
{
351401
fcopy_transaction.state = HVUTIL_DEVICE_DYING;
352-
cancel_delayed_work_sync(&fcopy_timeout_work);
402+
403+
hv_fcopy_cancel_work();
404+
353405
hvutil_transport_destroy(hvt);
354406
}

drivers/hv/hv_kvp.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,11 +758,50 @@ hv_kvp_init(struct hv_util_service *srv)
758758
return 0;
759759
}
760760

761-
void hv_kvp_deinit(void)
761+
static void hv_kvp_cancel_work(void)
762762
{
763-
kvp_transaction.state = HVUTIL_DEVICE_DYING;
764763
cancel_delayed_work_sync(&kvp_host_handshake_work);
765764
cancel_delayed_work_sync(&kvp_timeout_work);
766765
cancel_work_sync(&kvp_sendkey_work);
766+
}
767+
768+
int hv_kvp_pre_suspend(void)
769+
{
770+
struct vmbus_channel *channel = kvp_transaction.recv_channel;
771+
772+
tasklet_disable(&channel->callback_event);
773+
774+
/*
775+
* If there is a pending transtion, it's unnecessary to tell the host
776+
* that the transaction will fail, because that is implied when
777+
* util_suspend() calls vmbus_close() later.
778+
*/
779+
hv_kvp_cancel_work();
780+
781+
/*
782+
* Forece the state to READY to handle the ICMSGTYPE_NEGOTIATE message
783+
* later. The user space daemon may go out of order and its write()
784+
* may fail with EINVAL: this doesn't matter since the daemon will
785+
* reset the device by closing and re-opening it.
786+
*/
787+
kvp_transaction.state = HVUTIL_READY;
788+
return 0;
789+
}
790+
791+
int hv_kvp_pre_resume(void)
792+
{
793+
struct vmbus_channel *channel = kvp_transaction.recv_channel;
794+
795+
tasklet_enable(&channel->callback_event);
796+
797+
return 0;
798+
}
799+
800+
void hv_kvp_deinit(void)
801+
{
802+
kvp_transaction.state = HVUTIL_DEVICE_DYING;
803+
804+
hv_kvp_cancel_work();
805+
767806
hvutil_transport_destroy(hvt);
768807
}

drivers/hv/hv_snapshot.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,61 @@ hv_vss_init(struct hv_util_service *srv)
379379
return 0;
380380
}
381381

382-
void hv_vss_deinit(void)
382+
static void hv_vss_cancel_work(void)
383383
{
384-
vss_transaction.state = HVUTIL_DEVICE_DYING;
385384
cancel_delayed_work_sync(&vss_timeout_work);
386385
cancel_work_sync(&vss_handle_request_work);
386+
}
387+
388+
int hv_vss_pre_suspend(void)
389+
{
390+
struct vmbus_channel *channel = vss_transaction.recv_channel;
391+
struct hv_vss_msg *vss_msg;
392+
393+
/*
394+
* Fake a THAW message for the user space daemon in case the daemon
395+
* has frozen the file systems. It doesn't matter if there is already
396+
* a message pending to be delivered to the user space since we force
397+
* vss_transaction.state to be HVUTIL_READY, so the user space daemon's
398+
* write() will fail with EINVAL (see vss_on_msg()), and the daemon
399+
* will reset the device by closing and re-opening it.
400+
*/
401+
vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL);
402+
if (!vss_msg)
403+
return -ENOMEM;
404+
405+
tasklet_disable(&channel->callback_event);
406+
407+
vss_msg->vss_hdr.operation = VSS_OP_THAW;
408+
409+
/* Cancel any possible pending work. */
410+
hv_vss_cancel_work();
411+
412+
/* We don't care about the return value. */
413+
hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
414+
415+
kfree(vss_msg);
416+
417+
vss_transaction.state = HVUTIL_READY;
418+
419+
/* tasklet_enable() will be called in hv_vss_pre_resume(). */
420+
return 0;
421+
}
422+
423+
int hv_vss_pre_resume(void)
424+
{
425+
struct vmbus_channel *channel = vss_transaction.recv_channel;
426+
427+
tasklet_enable(&channel->callback_event);
428+
429+
return 0;
430+
}
431+
432+
void hv_vss_deinit(void)
433+
{
434+
vss_transaction.state = HVUTIL_DEVICE_DYING;
435+
436+
hv_vss_cancel_work();
437+
387438
hvutil_transport_destroy(hvt);
388439
}

0 commit comments

Comments
 (0)