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

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
...@@ -85,10 +85,10 @@ static int hid_start_in(struct hid_device *hid) ...@@ -85,10 +85,10 @@ static int hid_start_in(struct hid_device *hid)
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
spin_lock_irqsave(&usbhid->lock, flags); 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_DISCONNECTED, &usbhid->iofl) &&
!test_bit(HID_SUSPENDED, &usbhid->iofl) && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
if (rc != 0) { if (rc != 0) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl); clear_bit(HID_IN_RUNNING, &usbhid->iofl);
...@@ -272,13 +272,13 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) ...@@ -272,13 +272,13 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
static void hid_irq_in(struct urb *urb) static void hid_irq_in(struct urb *urb)
{ {
struct hid_device *hid = urb->context; struct hid_device *hid = urb->context;
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
int status; int status;
switch (urb->status) { switch (urb->status) {
case 0: /* success */ case 0: /* success */
usbhid->retry_delay = 0; usbhid->retry_delay = 0;
if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) if (!test_bit(HID_OPENED, &usbhid->iofl))
break; break;
usbhid_mark_busy(usbhid); usbhid_mark_busy(usbhid);
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
...@@ -692,6 +692,8 @@ static int usbhid_open(struct hid_device *hid) ...@@ -692,6 +692,8 @@ static int usbhid_open(struct hid_device *hid)
goto done; goto done;
} }
usbhid->intf->needs_remote_wakeup = 1; 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); set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
res = hid_start_in(hid); res = hid_start_in(hid);
if (res) { if (res) {
...@@ -701,6 +703,9 @@ static int usbhid_open(struct hid_device *hid) ...@@ -701,6 +703,9 @@ static int usbhid_open(struct hid_device *hid)
} else { } else {
/* no use opening if resources are insufficient */ /* no use opening if resources are insufficient */
hid->open--; hid->open--;
clear_bit(HID_OPENED, &usbhid->iofl);
if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL))
clear_bit(HID_IN_POLLING, &usbhid->iofl);
res = -EBUSY; res = -EBUSY;
usbhid->intf->needs_remote_wakeup = 0; usbhid->intf->needs_remote_wakeup = 0;
} }
...@@ -734,6 +739,9 @@ static void usbhid_close(struct hid_device *hid) ...@@ -734,6 +739,9 @@ static void usbhid_close(struct hid_device *hid)
*/ */
spin_lock_irq(&usbhid->lock); spin_lock_irq(&usbhid->lock);
if (!--hid->open) { 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); spin_unlock_irq(&usbhid->lock);
hid_cancel_delayed_stuff(usbhid); hid_cancel_delayed_stuff(usbhid);
if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) { if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
...@@ -1135,6 +1143,7 @@ static int usbhid_start(struct hid_device *hid) ...@@ -1135,6 +1143,7 @@ static int usbhid_start(struct hid_device *hid)
ret = usb_autopm_get_interface(usbhid->intf); ret = usb_autopm_get_interface(usbhid->intf);
if (ret) if (ret)
goto fail; goto fail;
set_bit(HID_IN_POLLING, &usbhid->iofl);
usbhid->intf->needs_remote_wakeup = 1; usbhid->intf->needs_remote_wakeup = 1;
ret = hid_start_in(hid); ret = hid_start_in(hid);
if (ret) { if (ret) {
...@@ -1176,8 +1185,10 @@ static void usbhid_stop(struct hid_device *hid) ...@@ -1176,8 +1185,10 @@ static void usbhid_stop(struct hid_device *hid)
if (WARN_ON(!usbhid)) if (WARN_ON(!usbhid))
return; 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; usbhid->intf->needs_remote_wakeup = 0;
}
clear_bit(HID_STARTED, &usbhid->iofl); clear_bit(HID_STARTED, &usbhid->iofl);
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
......
...@@ -49,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor); ...@@ -49,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_KEYS_PRESSED 10 #define HID_KEYS_PRESSED 10
#define HID_NO_BANDWIDTH 11 #define HID_NO_BANDWIDTH 11
#define HID_RESUME_RUNNING 12 #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 * USB-specific HID struct, to be pointed to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment