提交 10ca4425 编写于 作者: J Jiri Slaby 提交者: Greg Kroah-Hartman

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: NJiri Slaby <jslaby@suse.cz>
Cc: Craig W. Nadler <craig@nadler.us>
Acked-by: NDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 1c815577
...@@ -82,7 +82,7 @@ static struct class *usb_gadget_class; ...@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
struct printer_dev { struct printer_dev {
spinlock_t lock; /* lock this structure */ spinlock_t lock; /* lock this structure */
/* lock buffer lists during read/write calls */ /* lock buffer lists during read/write calls */
spinlock_t lock_printer_io; struct mutex lock_printer_io;
struct usb_gadget *gadget; struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */ struct usb_request *req; /* for control responses */
u8 config; u8 config;
...@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -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); 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); spin_lock_irqsave(&dev->lock, flags);
/* We will use this flag later to check if a printer reset happened /* 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) ...@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
* call or not. * call or not.
*/ */
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
...@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) { if (dev->reset_printer) {
list_add(&current_rx_req->list, &dev->rx_reqs); list_add(&current_rx_req->list, &dev->rx_reqs);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
...@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -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; dev->current_rx_buf = current_rx_buf;
spin_unlock_irqrestore(&dev->lock, flags); 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); 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) ...@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (len == 0) if (len == 0)
return -EINVAL; return -EINVAL;
spin_lock(&dev->lock_printer_io); mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
/* Check if a printer reset happens while we have interrupts on */ /* 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) ...@@ -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. * a NON-Blocking call or not.
*/ */
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
...@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -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)) { if (copy_from_user(req->buf, buf, size)) {
list_add(&req->list, &dev->tx_reqs); list_add(&req->list, &dev->tx_reqs);
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return bytes_copied; return bytes_copied;
} }
...@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) { if (dev->reset_printer) {
list_add(&req->list, &dev->tx_reqs); list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
list_add(&req->list, &dev->tx_reqs); list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
spin_unlock(&dev->lock_printer_io); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
...@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -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_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); DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
...@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait) ...@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
unsigned long flags; unsigned long flags;
int status = 0; int status = 0;
spin_lock(&dev->lock_printer_io); mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
setup_rx_reqs(dev); setup_rx_reqs(dev);
spin_unlock_irqrestore(&dev->lock, flags); 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->rx_wait, wait);
poll_wait(fd, &dev->tx_wait, wait); poll_wait(fd, &dev->tx_wait, wait);
...@@ -1461,7 +1461,7 @@ printer_bind(struct usb_gadget *gadget) ...@@ -1461,7 +1461,7 @@ printer_bind(struct usb_gadget *gadget)
} }
spin_lock_init(&dev->lock); 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);
INIT_LIST_HEAD(&dev->tx_reqs_active); INIT_LIST_HEAD(&dev->tx_reqs_active);
INIT_LIST_HEAD(&dev->rx_reqs); INIT_LIST_HEAD(&dev->rx_reqs);
...@@ -1594,7 +1594,7 @@ cleanup(void) ...@@ -1594,7 +1594,7 @@ cleanup(void)
{ {
int status; int status;
spin_lock(&usb_printer_gadget.lock_printer_io); mutex_lock(&usb_printer_gadget.lock_printer_io);
class_destroy(usb_gadget_class); class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 2); unregister_chrdev_region(g_printer_devno, 2);
...@@ -1602,6 +1602,6 @@ cleanup(void) ...@@ -1602,6 +1602,6 @@ cleanup(void)
if (status) if (status)
ERROR(dev, "usb_gadget_unregister_driver %x\n", 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); module_exit(cleanup);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册