The URB complete handler may be called by usb_unlink_urb directly, so deadlock will be triggered in __usbhid_submit_report since usbhid->lock is to be acquired in ctrl/out URB complete handler but it is hold before calling usb_unlink_urb. This patch avoids the deadlock by releasing the lock before calling usb_unlink_urb. CC: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxxxxx> --- drivers/hid/usbhid/hid-core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index aa1c503..b5d07da 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -543,11 +543,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re * the queue is known to run * but an earlier request may be stuck * we may need to time out - * no race because this is called under - * spinlock + * release spinlock to avoid deadlock. */ - if (time_after(jiffies, usbhid->last_out + HZ * 5)) + if (time_after(jiffies, usbhid->last_out + HZ * 5)) { + spin_unlock(&usbhid->lock); usb_unlink_urb(usbhid->urbout); + spin_lock(&usbhid->lock); + } } return; } @@ -591,11 +593,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re * the queue is known to run * but an earlier request may be stuck * we may need to time out - * no race because this is called under - * spinlock + * release spinlock to avoid deadlock. */ - if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) + if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { + spin_unlock(&usbhid->lock); usb_unlink_urb(usbhid->urbctrl); + spin_lock(&usbhid->lock); + } } } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html