| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2009, Citrix Systems, Inc. |
|---|
| 3 | 4 | * Copyright (c) 2010, Microsoft Corporation. |
|---|
| 4 | 5 | * Copyright (c) 2011, Novell Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 8 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | 6 | */ |
|---|
| 15 | 7 | #include <linux/init.h> |
|---|
| 16 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 112 | 104 | |
|---|
| 113 | 105 | #pragma pack(pop) |
|---|
| 114 | 106 | |
|---|
| 115 | | -#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) |
|---|
| 116 | | -#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) |
|---|
| 107 | +#define INPUTVSC_SEND_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024) |
|---|
| 108 | +#define INPUTVSC_RECV_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024) |
|---|
| 117 | 109 | |
|---|
| 118 | 110 | |
|---|
| 119 | 111 | enum pipe_prot_msg_type { |
|---|
| .. | .. |
|---|
| 200 | 192 | if (desc->bLength == 0) |
|---|
| 201 | 193 | goto cleanup; |
|---|
| 202 | 194 | |
|---|
| 195 | + /* The pointer is not NULL when we resume from hibernation */ |
|---|
| 196 | + kfree(input_device->hid_desc); |
|---|
| 203 | 197 | input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC); |
|---|
| 204 | 198 | |
|---|
| 205 | 199 | if (!input_device->hid_desc) |
|---|
| .. | .. |
|---|
| 211 | 205 | goto cleanup; |
|---|
| 212 | 206 | } |
|---|
| 213 | 207 | |
|---|
| 208 | + /* The pointer is not NULL when we resume from hibernation */ |
|---|
| 209 | + kfree(input_device->report_desc); |
|---|
| 214 | 210 | input_device->report_desc = kzalloc(input_device->report_desc_size, |
|---|
| 215 | 211 | GFP_ATOMIC); |
|---|
| 216 | 212 | |
|---|
| .. | .. |
|---|
| 349 | 345 | struct mousevsc_dev *input_dev = hv_get_drvdata(device); |
|---|
| 350 | 346 | struct mousevsc_prt_msg *request; |
|---|
| 351 | 347 | struct mousevsc_prt_msg *response; |
|---|
| 348 | + |
|---|
| 349 | + reinit_completion(&input_dev->wait_event); |
|---|
| 352 | 350 | |
|---|
| 353 | 351 | request = &input_dev->protocol_req; |
|---|
| 354 | 352 | memset(request, 0, sizeof(struct mousevsc_prt_msg)); |
|---|
| .. | .. |
|---|
| 500 | 498 | |
|---|
| 501 | 499 | ret = hid_add_device(hid_dev); |
|---|
| 502 | 500 | if (ret) |
|---|
| 503 | | - goto probe_err1; |
|---|
| 501 | + goto probe_err2; |
|---|
| 504 | 502 | |
|---|
| 505 | 503 | |
|---|
| 506 | 504 | ret = hid_parse(hid_dev); |
|---|
| .. | .. |
|---|
| 549 | 547 | return 0; |
|---|
| 550 | 548 | } |
|---|
| 551 | 549 | |
|---|
| 550 | +static int mousevsc_suspend(struct hv_device *dev) |
|---|
| 551 | +{ |
|---|
| 552 | + vmbus_close(dev->channel); |
|---|
| 553 | + |
|---|
| 554 | + return 0; |
|---|
| 555 | +} |
|---|
| 556 | + |
|---|
| 557 | +static int mousevsc_resume(struct hv_device *dev) |
|---|
| 558 | +{ |
|---|
| 559 | + int ret; |
|---|
| 560 | + |
|---|
| 561 | + ret = vmbus_open(dev->channel, |
|---|
| 562 | + INPUTVSC_SEND_RING_BUFFER_SIZE, |
|---|
| 563 | + INPUTVSC_RECV_RING_BUFFER_SIZE, |
|---|
| 564 | + NULL, 0, |
|---|
| 565 | + mousevsc_on_channel_callback, |
|---|
| 566 | + dev); |
|---|
| 567 | + if (ret) |
|---|
| 568 | + return ret; |
|---|
| 569 | + |
|---|
| 570 | + ret = mousevsc_connect_to_vsp(dev); |
|---|
| 571 | + return ret; |
|---|
| 572 | +} |
|---|
| 573 | + |
|---|
| 552 | 574 | static const struct hv_vmbus_device_id id_table[] = { |
|---|
| 553 | 575 | /* Mouse guid */ |
|---|
| 554 | 576 | { HV_MOUSE_GUID, }, |
|---|
| .. | .. |
|---|
| 562 | 584 | .id_table = id_table, |
|---|
| 563 | 585 | .probe = mousevsc_probe, |
|---|
| 564 | 586 | .remove = mousevsc_remove, |
|---|
| 587 | + .suspend = mousevsc_suspend, |
|---|
| 588 | + .resume = mousevsc_resume, |
|---|
| 565 | 589 | .driver = { |
|---|
| 566 | 590 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
|---|
| 567 | 591 | }, |
|---|
| .. | .. |
|---|
| 578 | 602 | } |
|---|
| 579 | 603 | |
|---|
| 580 | 604 | MODULE_LICENSE("GPL"); |
|---|
| 605 | +MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic HID Driver"); |
|---|
| 606 | + |
|---|
| 581 | 607 | module_init(mousevsc_init); |
|---|
| 582 | 608 | module_exit(mousevsc_exit); |
|---|