Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10ca4425 authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

USB: gadget/printer, fix sleep inside atomic



Stanse found that sleep is called inside atomic context created by
lock_printer_io spinlock in several functions. It's used in process
context only and some functions sleep inside its critical section. As
this is not allowed for spinlocks, switch it to mutex.

Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Cc: Craig W. Nadler <craig@nadler.us>
Acked-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 1c815577
Loading
Loading
Loading
Loading
+16 −16
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
struct printer_dev {
	spinlock_t		lock;		/* lock this structure */
	/* lock buffer lists during read/write calls */
	spinlock_t		lock_printer_io;
	struct mutex		lock_printer_io;
	struct usb_gadget	*gadget;
	struct usb_request	*req;		/* for control responses */
	u8			config;
@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)

	DBG(dev, "printer_read trying to read %d bytes\n", (int)len);

	spin_lock(&dev->lock_printer_io);
	mutex_lock(&dev->lock_printer_io);
	spin_lock_irqsave(&dev->lock, flags);

	/* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
		 * call or not.
		 */
		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return -EAGAIN;
		}

@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
		if (dev->reset_printer) {
			list_add(&current_rx_req->list, &dev->rx_reqs);
			spin_unlock_irqrestore(&dev->lock, flags);
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return -EAGAIN;
		}

@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
	dev->current_rx_buf = current_rx_buf;

	spin_unlock_irqrestore(&dev->lock, flags);
	spin_unlock(&dev->lock_printer_io);
	mutex_unlock(&dev->lock_printer_io);

	DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);

@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
	if (len == 0)
		return -EINVAL;

	spin_lock(&dev->lock_printer_io);
	mutex_lock(&dev->lock_printer_io);
	spin_lock_irqsave(&dev->lock, flags);

	/* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
		 * a NON-Blocking call or not.
		 */
		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return -EAGAIN;
		}

@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)

		if (copy_from_user(req->buf, buf, size)) {
			list_add(&req->list, &dev->tx_reqs);
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return bytes_copied;
		}

@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
		if (dev->reset_printer) {
			list_add(&req->list, &dev->tx_reqs);
			spin_unlock_irqrestore(&dev->lock, flags);
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return -EAGAIN;
		}

		if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
			list_add(&req->list, &dev->tx_reqs);
			spin_unlock_irqrestore(&dev->lock, flags);
			spin_unlock(&dev->lock_printer_io);
			mutex_unlock(&dev->lock_printer_io);
			return -EAGAIN;
		}

@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
	}

	spin_unlock_irqrestore(&dev->lock, flags);
	spin_unlock(&dev->lock_printer_io);
	mutex_unlock(&dev->lock_printer_io);

	DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);

@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
	unsigned long		flags;
	int			status = 0;

	spin_lock(&dev->lock_printer_io);
	mutex_lock(&dev->lock_printer_io);
	spin_lock_irqsave(&dev->lock, flags);
	setup_rx_reqs(dev);
	spin_unlock_irqrestore(&dev->lock, flags);
	spin_unlock(&dev->lock_printer_io);
	mutex_unlock(&dev->lock_printer_io);

	poll_wait(fd, &dev->rx_wait, wait);
	poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@ printer_bind(struct usb_gadget *gadget)
	}

	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->lock_printer_io);
	mutex_init(&dev->lock_printer_io);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->tx_reqs_active);
	INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@ cleanup(void)
{
	int status;

	spin_lock(&usb_printer_gadget.lock_printer_io);
	mutex_lock(&usb_printer_gadget.lock_printer_io);
	class_destroy(usb_gadget_class);
	unregister_chrdev_region(g_printer_devno, 2);

@@ -1602,6 +1602,6 @@ cleanup(void)
	if (status)
		ERROR(dev, "usb_gadget_unregister_driver %x\n", status);

	spin_unlock(&usb_printer_gadget.lock_printer_io);
	mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);