commit 072684e8c58d17e853f8e8b9f6d9ce2e58d2b036 upstream.
In f_hidg_write() the write_spinlock is acquired before calling usb_ep_queue() which causes a deadlock when dummy_hcd is being used. This is because dummy_queue() callbacks into f_hidg_req_complete() which tries to acquire the same spinlock. This is (part of) the backtrace when the deadlock occurs:
0xffffffffc06b1410 in f_hidg_req_complete 0xffffffffc06a590a in usb_gadget_giveback_request 0xffffffffc06cfff2 in dummy_queue 0xffffffffc06a4b96 in usb_ep_queue 0xffffffffc06b1eb6 in f_hidg_write 0xffffffff8127730b in __vfs_write 0xffffffff812774d1 in vfs_write 0xffffffff81277725 in SYSC_write
Fix this by releasing the write_spinlock before calling usb_ep_queue()
Reviewed-by: James Bottomley James.Bottomley@HansenPartnership.com Tested-by: James Bottomley James.Bottomley@HansenPartnership.com Cc: stable@vger.kernel.org Fixes: 749494b6bdbb ("usb: gadget: f_hid: fix: Move IN request allocation to set_alt()") Signed-off-by: Radoslav Gerganov rgerganov@vmware.com Signed-off-by: Felipe Balbi felipe.balbi@linux.intel.com --- drivers/usb/gadget/function/f_hid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 5815120..8e83649 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -340,20 +340,20 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, req->complete = f_hidg_req_complete; req->context = hidg;
+ spin_unlock_irqrestore(&hidg->write_spinlock, flags); + status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); if (status < 0) { ERROR(hidg->func.config->cdev, "usb_ep_queue error on int endpoint %zd\n", status); - goto release_write_pending_unlocked; + goto release_write_pending; } else { status = count; } - spin_unlock_irqrestore(&hidg->write_spinlock, flags);
return status; release_write_pending: spin_lock_irqsave(&hidg->write_spinlock, flags); -release_write_pending_unlocked: hidg->write_pending = 0; spin_unlock_irqrestore(&hidg->write_spinlock, flags);
On 1.04.2019 13:54, Radoslav Gerganov wrote:
commit 072684e8c58d17e853f8e8b9f6d9ce2e58d2b036 upstream.
In f_hidg_write() the write_spinlock is acquired before calling usb_ep_queue() which causes a deadlock when dummy_hcd is being used. This is because dummy_queue() callbacks into f_hidg_req_complete() which tries to acquire the same spinlock. This is (part of) the backtrace when the deadlock occurs:
This is the backport of commit 072684e8c to the stable 4.9 branch. I missed to point that in the subject line, sorry.
Thanks, Rado
On Mon, Apr 01, 2019 at 10:58:57AM +0000, Radoslav Gerganov wrote:
On 1.04.2019 13:54, Radoslav Gerganov wrote:
commit 072684e8c58d17e853f8e8b9f6d9ce2e58d2b036 upstream.
In f_hidg_write() the write_spinlock is acquired before calling usb_ep_queue() which causes a deadlock when dummy_hcd is being used. This is because dummy_queue() callbacks into f_hidg_req_complete() which tries to acquire the same spinlock. This is (part of) the backtrace when the deadlock occurs:
This is the backport of commit 072684e8c to the stable 4.9 branch. I missed to point that in the subject line, sorry.
Not a problem at all, thanks for the backport, now queued up.
greg k-h
linux-stable-mirror@lists.linaro.org