summary refs log tree commit diff
path: root/drivers/usb
diff options
context:
space:
mode:
authorYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>2017-09-13 15:31:33 +0900
committerFelipe Balbi <felipe.balbi@linux.intel.com>2017-09-20 14:57:28 +0300
commit9ada8c582088d32bd5c071c17213bc6edf37443a (patch)
treef08cbd1a2cc3d37581d2bba9f0e8a8670a5369e4 /drivers/usb
parent97e133d54c1ca8948b191e5721a145a76c4db33d (diff)
downloadlinux-9ada8c582088d32bd5c071c17213bc6edf37443a.tar.gz
usb: gadget: function: printer: avoid spinlock recursion
If usb_gadget_giveback_request() is called in usb_ep_queue(),
this printer_write() is possible to cause spinlock recursion. So,
this patch adds spin_unlock() before calls usb_ep_queue() to avoid it.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/function/f_printer.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 8df244fc9d80..ea0da35a44e2 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 	size_t			size;	/* Amount of data in a TX request. */
 	size_t			bytes_copied = 0;
 	struct usb_request	*req;
+	int			value;
 
 	DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
 
@@ -634,7 +635,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 			return -EAGAIN;
 		}
 
-		if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
+		/* here, we unlock, and only unlock, to avoid deadlock. */
+		spin_unlock(&dev->lock);
+		value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
+		spin_lock(&dev->lock);
+		if (value) {
 			list_add(&req->list, &dev->tx_reqs);
 			spin_unlock_irqrestore(&dev->lock, flags);
 			mutex_unlock(&dev->lock_printer_io);