diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2017-07-12 20:14:24 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-07-21 12:14:03 -0400 |
commit | cf601774c9f23078010adc9e6cd29470fafa5678 (patch) | |
tree | 0c81324a25d929d3f9acefd1f9a770bcea8ed15d | |
parent | 929b60a85b731d803f2b7829149496479eba0b20 (diff) |
HID: usbhid: fix "always poll" quirk
Even though the IO for devices with "always poll" quirk is already running,
we still need to set HID_OPENED bit in usbhid->iofl so the interrupt
handler does not ignore the data coming from the device.
Reported-by: Olof Johansson <olof@lixom.net>
Tested-by: Olof Johansson <olof@lixom.net>
Fixes: e399396a6b0 ("HID: usbhid: remove custom locking from usbhid_open...")
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 76013eb5cb7f..c008847e0b20 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -680,18 +680,21 @@ static int usbhid_open(struct hid_device *hid) | |||
680 | struct usbhid_device *usbhid = hid->driver_data; | 680 | struct usbhid_device *usbhid = hid->driver_data; |
681 | int res; | 681 | int res; |
682 | 682 | ||
683 | set_bit(HID_OPENED, &usbhid->iofl); | ||
684 | |||
683 | if (hid->quirks & HID_QUIRK_ALWAYS_POLL) | 685 | if (hid->quirks & HID_QUIRK_ALWAYS_POLL) |
684 | return 0; | 686 | return 0; |
685 | 687 | ||
686 | res = usb_autopm_get_interface(usbhid->intf); | 688 | res = usb_autopm_get_interface(usbhid->intf); |
687 | /* the device must be awake to reliably request remote wakeup */ | 689 | /* the device must be awake to reliably request remote wakeup */ |
688 | if (res < 0) | 690 | if (res < 0) { |
691 | clear_bit(HID_OPENED, &usbhid->iofl); | ||
689 | return -EIO; | 692 | return -EIO; |
693 | } | ||
690 | 694 | ||
691 | usbhid->intf->needs_remote_wakeup = 1; | 695 | usbhid->intf->needs_remote_wakeup = 1; |
692 | 696 | ||
693 | set_bit(HID_RESUME_RUNNING, &usbhid->iofl); | 697 | set_bit(HID_RESUME_RUNNING, &usbhid->iofl); |
694 | set_bit(HID_OPENED, &usbhid->iofl); | ||
695 | set_bit(HID_IN_POLLING, &usbhid->iofl); | 698 | set_bit(HID_IN_POLLING, &usbhid->iofl); |
696 | 699 | ||
697 | res = hid_start_in(hid); | 700 | res = hid_start_in(hid); |
@@ -727,19 +730,20 @@ static void usbhid_close(struct hid_device *hid) | |||
727 | { | 730 | { |
728 | struct usbhid_device *usbhid = hid->driver_data; | 731 | struct usbhid_device *usbhid = hid->driver_data; |
729 | 732 | ||
730 | if (hid->quirks & HID_QUIRK_ALWAYS_POLL) | ||
731 | return; | ||
732 | |||
733 | /* | 733 | /* |
734 | * Make sure we don't restart data acquisition due to | 734 | * Make sure we don't restart data acquisition due to |
735 | * a resumption we no longer care about by avoiding racing | 735 | * a resumption we no longer care about by avoiding racing |
736 | * with hid_start_in(). | 736 | * with hid_start_in(). |
737 | */ | 737 | */ |
738 | spin_lock_irq(&usbhid->lock); | 738 | spin_lock_irq(&usbhid->lock); |
739 | clear_bit(HID_IN_POLLING, &usbhid->iofl); | ||
740 | clear_bit(HID_OPENED, &usbhid->iofl); | 739 | clear_bit(HID_OPENED, &usbhid->iofl); |
740 | if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) | ||
741 | clear_bit(HID_IN_POLLING, &usbhid->iofl); | ||
741 | spin_unlock_irq(&usbhid->lock); | 742 | spin_unlock_irq(&usbhid->lock); |
742 | 743 | ||
744 | if (hid->quirks & HID_QUIRK_ALWAYS_POLL) | ||
745 | return; | ||
746 | |||
743 | hid_cancel_delayed_stuff(usbhid); | 747 | hid_cancel_delayed_stuff(usbhid); |
744 | usb_kill_urb(usbhid->urbin); | 748 | usb_kill_urb(usbhid->urbin); |
745 | usbhid->intf->needs_remote_wakeup = 0; | 749 | usbhid->intf->needs_remote_wakeup = 0; |