aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2018-06-19 17:59:44 -0400
committerJiri Kosina <jkosina@suse.cz>2018-06-25 09:24:46 -0400
commitf49255e00c2e085b1467087d2dbb6b01d7042cc8 (patch)
tree788ba8ee2e5541105ac48e523355d34a0a6ee7e8 /drivers/hid
parentdc9b8e85ed95cbe7e3ad0eabb5b48d617bbc365e (diff)
HID: usbhid: use irqsave() in USB's complete callback
The USB completion callback does not disable interrupts while acquiring the ->lock. We want to remove the local_irq_disable() invocation from __usb_hcd_giveback_urb() and therefore it is required for the callback handler to disable the interrupts while acquiring the lock. The callback may be invoked either in IRQ or BH context depending on the USB host controller. Use the _irqsave() variant of the locking primitives. Cc: Jiri Kosina <jikos@kernel.org> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com> Cc: linux-input@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/usbhid/hid-core.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index af0e0d061b15..11103efebbaa 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -480,6 +480,7 @@ static void hid_ctrl(struct urb *urb)
480{ 480{
481 struct hid_device *hid = urb->context; 481 struct hid_device *hid = urb->context;
482 struct usbhid_device *usbhid = hid->driver_data; 482 struct usbhid_device *usbhid = hid->driver_data;
483 unsigned long flags;
483 int unplug = 0, status = urb->status; 484 int unplug = 0, status = urb->status;
484 485
485 switch (status) { 486 switch (status) {
@@ -501,7 +502,7 @@ static void hid_ctrl(struct urb *urb)
501 hid_warn(urb->dev, "ctrl urb status %d received\n", status); 502 hid_warn(urb->dev, "ctrl urb status %d received\n", status);
502 } 503 }
503 504
504 spin_lock(&usbhid->lock); 505 spin_lock_irqsave(&usbhid->lock, flags);
505 506
506 if (unplug) { 507 if (unplug) {
507 usbhid->ctrltail = usbhid->ctrlhead; 508 usbhid->ctrltail = usbhid->ctrlhead;
@@ -511,13 +512,13 @@ static void hid_ctrl(struct urb *urb)
511 if (usbhid->ctrlhead != usbhid->ctrltail && 512 if (usbhid->ctrlhead != usbhid->ctrltail &&
512 hid_submit_ctrl(hid) == 0) { 513 hid_submit_ctrl(hid) == 0) {
513 /* Successfully submitted next urb in queue */ 514 /* Successfully submitted next urb in queue */
514 spin_unlock(&usbhid->lock); 515 spin_unlock_irqrestore(&usbhid->lock, flags);
515 return; 516 return;
516 } 517 }
517 } 518 }
518 519
519 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); 520 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
520 spin_unlock(&usbhid->lock); 521 spin_unlock_irqrestore(&usbhid->lock, flags);
521 usb_autopm_put_interface_async(usbhid->intf); 522 usb_autopm_put_interface_async(usbhid->intf);
522 wake_up(&usbhid->wait); 523 wake_up(&usbhid->wait);
523} 524}