Skip to content

Commit af13f9e

Browse files
dcuiSasha Levin
authored andcommitted
HID: hyperv: Add the support of hibernation
During the suspend process and resume process, if there is any mouse event, there is a small chance the suspend and the resume process can be aborted because of mousevsc_on_receive() -> pm_wakeup_hard_event(). This behavior can be avoided by disabling the Hyper-V mouse device as a wakeup source: echo disabled > /sys/bus/vmbus/drivers/hid_hyperv/XXX/power/wakeup (XXX is the device's GUID). Signed-off-by: Dexuan Cui <[email protected]> Acked-by: Jiri Kosina <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 25bd2b2 commit af13f9e

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

drivers/hid/hid-hyperv.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
192192
if (desc->bLength == 0)
193193
goto cleanup;
194194

195+
/* The pointer is not NULL when we resume from hibernation */
196+
if (input_device->hid_desc != NULL)
197+
kfree(input_device->hid_desc);
195198
input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
196199

197200
if (!input_device->hid_desc)
@@ -203,6 +206,9 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
203206
goto cleanup;
204207
}
205208

209+
/* The pointer is not NULL when we resume from hibernation */
210+
if (input_device->report_desc != NULL)
211+
kfree(input_device->report_desc);
206212
input_device->report_desc = kzalloc(input_device->report_desc_size,
207213
GFP_ATOMIC);
208214

@@ -342,6 +348,8 @@ static int mousevsc_connect_to_vsp(struct hv_device *device)
342348
struct mousevsc_prt_msg *request;
343349
struct mousevsc_prt_msg *response;
344350

351+
reinit_completion(&input_dev->wait_event);
352+
345353
request = &input_dev->protocol_req;
346354
memset(request, 0, sizeof(struct mousevsc_prt_msg));
347355

@@ -541,6 +549,30 @@ static int mousevsc_remove(struct hv_device *dev)
541549
return 0;
542550
}
543551

552+
static int mousevsc_suspend(struct hv_device *dev)
553+
{
554+
vmbus_close(dev->channel);
555+
556+
return 0;
557+
}
558+
559+
static int mousevsc_resume(struct hv_device *dev)
560+
{
561+
int ret;
562+
563+
ret = vmbus_open(dev->channel,
564+
INPUTVSC_SEND_RING_BUFFER_SIZE,
565+
INPUTVSC_RECV_RING_BUFFER_SIZE,
566+
NULL, 0,
567+
mousevsc_on_channel_callback,
568+
dev);
569+
if (ret)
570+
return ret;
571+
572+
ret = mousevsc_connect_to_vsp(dev);
573+
return ret;
574+
}
575+
544576
static const struct hv_vmbus_device_id id_table[] = {
545577
/* Mouse guid */
546578
{ HV_MOUSE_GUID, },
@@ -554,6 +586,8 @@ static struct hv_driver mousevsc_drv = {
554586
.id_table = id_table,
555587
.probe = mousevsc_probe,
556588
.remove = mousevsc_remove,
589+
.suspend = mousevsc_suspend,
590+
.resume = mousevsc_resume,
557591
.driver = {
558592
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
559593
},

0 commit comments

Comments
 (0)