Input: hyperv-keyboard: Add the support of hibernation
authorDexuan Cui <decui@microsoft.com>
Mon, 6 Jan 2020 22:40:44 +0000 (14:40 -0800)
committerSasha Levin <sashal@kernel.org>
Sat, 25 Jan 2020 21:52:11 +0000 (16:52 -0500)
Add suspend() and resume() functions so the Hyper-V virtual keyboard
can participate in VM hibernation.

Note that the keyboard is a "wakeup" device that could abort an in-progress
hibernation if there is keyboard event.  No attempt is made to suppress this
behavior.  If desired, a sysadmin can disable the keyboard as a wakeup device
using standard mechanisms such as:

echo disabled > /sys/bus/vmbus/drivers/hyperv_keyboard/XXX/power/wakeup
(where XXX is the device's GUID)

Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/input/serio/hyperv-keyboard.c

index e486a8a74c40c710de93a6de132e15089043d3a3..df4e9f6f4529d749833e2ca8f903d3ff6436ab4a 100644 (file)
@@ -259,6 +259,8 @@ static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev)
        u32 proto_status;
        int error;
 
+       reinit_completion(&kbd_dev->wait_event);
+
        request = &kbd_dev->protocol_req;
        memset(request, 0, sizeof(struct synth_kbd_protocol_request));
        request->header.type = __cpu_to_le32(SYNTH_KBD_PROTOCOL_REQUEST);
@@ -380,6 +382,29 @@ static int hv_kbd_remove(struct hv_device *hv_dev)
        return 0;
 }
 
+static int hv_kbd_suspend(struct hv_device *hv_dev)
+{
+       vmbus_close(hv_dev->channel);
+
+       return 0;
+}
+
+static int hv_kbd_resume(struct hv_device *hv_dev)
+{
+       int ret;
+
+       ret = vmbus_open(hv_dev->channel,
+                        KBD_VSC_SEND_RING_BUFFER_SIZE,
+                        KBD_VSC_RECV_RING_BUFFER_SIZE,
+                        NULL, 0,
+                        hv_kbd_on_channel_callback,
+                        hv_dev);
+       if (ret == 0)
+               ret = hv_kbd_connect_to_vsp(hv_dev);
+
+       return ret;
+}
+
 static const struct hv_vmbus_device_id id_table[] = {
        /* Keyboard guid */
        { HV_KBD_GUID, },
@@ -393,6 +418,8 @@ static struct  hv_driver hv_kbd_drv = {
        .id_table = id_table,
        .probe = hv_kbd_probe,
        .remove = hv_kbd_remove,
+       .suspend = hv_kbd_suspend,
+       .resume = hv_kbd_resume,
        .driver = {
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },