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

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

HID: usbhid: do not rely on hid->open when deciding to do IO



Instead of checking hid->open (that we plan on having HID core manage) in
hid_start_in(), let's allocate a couple of new flags: HID_IN_POLLING and
HID_OPENED, and use them to decide whether we should be submitting URBs or
not.

Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 9a83563f
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ static int hid_start_in(struct hid_device *hid)
	struct usbhid_device *usbhid = hid->driver_data;

	spin_lock_irqsave(&usbhid->lock, flags);
	if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) &&
	if (test_bit(HID_IN_POLLING, &usbhid->iofl) &&
	    !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
	    !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
	    !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
@@ -278,7 +278,7 @@ static void hid_irq_in(struct urb *urb)
	switch (urb->status) {
	case 0:			/* success */
		usbhid->retry_delay = 0;
		if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
		if (!test_bit(HID_OPENED, &usbhid->iofl))
			break;
		usbhid_mark_busy(usbhid);
		if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
@@ -692,6 +692,8 @@ static int usbhid_open(struct hid_device *hid)
			goto done;
		}
		usbhid->intf->needs_remote_wakeup = 1;
		set_bit(HID_OPENED, &usbhid->iofl);
		set_bit(HID_IN_POLLING, &usbhid->iofl);
		set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
		res = hid_start_in(hid);
		if (res) {
@@ -701,6 +703,9 @@ static int usbhid_open(struct hid_device *hid)
			} else {
				/* no use opening if resources are insufficient */
				hid->open--;
				clear_bit(HID_OPENED, &usbhid->iofl);
				if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL))
					clear_bit(HID_IN_POLLING, &usbhid->iofl);
				res = -EBUSY;
				usbhid->intf->needs_remote_wakeup = 0;
			}
@@ -734,6 +739,9 @@ static void usbhid_close(struct hid_device *hid)
	 */
	spin_lock_irq(&usbhid->lock);
	if (!--hid->open) {
		if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL))
			clear_bit(HID_IN_POLLING, &usbhid->iofl);
		clear_bit(HID_OPENED, &usbhid->iofl);
		spin_unlock_irq(&usbhid->lock);
		hid_cancel_delayed_stuff(usbhid);
		if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
@@ -1135,6 +1143,7 @@ static int usbhid_start(struct hid_device *hid)
		ret = usb_autopm_get_interface(usbhid->intf);
		if (ret)
			goto fail;
		set_bit(HID_IN_POLLING, &usbhid->iofl);
		usbhid->intf->needs_remote_wakeup = 1;
		ret = hid_start_in(hid);
		if (ret) {
@@ -1176,8 +1185,10 @@ static void usbhid_stop(struct hid_device *hid)
	if (WARN_ON(!usbhid))
		return;

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
	if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
		clear_bit(HID_IN_POLLING, &usbhid->iofl);
		usbhid->intf->needs_remote_wakeup = 0;
	}

	clear_bit(HID_STARTED, &usbhid->iofl);
	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
+11 −0
Original line number Diff line number Diff line
@@ -49,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_KEYS_PRESSED	10
#define HID_NO_BANDWIDTH	11
#define HID_RESUME_RUNNING	12
/*
 * The device is opened, meaning there is a client that is interested
 * in data coming from the device.
 */
#define HID_OPENED		13
/*
 * We are polling input endpoint by [re]submitting IN URB, because
 * either HID device is opened or ALWAYS POLL quirk is set for the
 * device.
 */
#define HID_IN_POLLING		14

/*
 * USB-specific HID struct, to be pointed to