Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf601774 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Jiri Kosina
Browse files

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: default avatarOlof Johansson <olof@lixom.net>
Tested-by: default avatarOlof Johansson <olof@lixom.net>
Fixes: e399396a ("HID: usbhid: remove custom locking from usbhid_open...")
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 929b60a8
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -680,18 +680,21 @@ static int usbhid_open(struct hid_device *hid)
	struct usbhid_device *usbhid = hid->driver_data;
	int res;

	set_bit(HID_OPENED, &usbhid->iofl);

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
		return 0;

	res = usb_autopm_get_interface(usbhid->intf);
	/* the device must be awake to reliably request remote wakeup */
	if (res < 0)
	if (res < 0) {
		clear_bit(HID_OPENED, &usbhid->iofl);
		return -EIO;
	}

	usbhid->intf->needs_remote_wakeup = 1;

	set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
	set_bit(HID_OPENED, &usbhid->iofl);
	set_bit(HID_IN_POLLING, &usbhid->iofl);

	res = hid_start_in(hid);
@@ -727,19 +730,20 @@ static void usbhid_close(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
		return;

	/*
	 * Make sure we don't restart data acquisition due to
	 * a resumption we no longer care about by avoiding racing
	 * with hid_start_in().
	 */
	spin_lock_irq(&usbhid->lock);
	clear_bit(HID_IN_POLLING, &usbhid->iofl);
	clear_bit(HID_OPENED, &usbhid->iofl);
	if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL))
		clear_bit(HID_IN_POLLING, &usbhid->iofl);
	spin_unlock_irq(&usbhid->lock);

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
		return;

	hid_cancel_delayed_stuff(usbhid);
	usb_kill_urb(usbhid->urbin);
	usbhid->intf->needs_remote_wakeup = 0;