Skip to content

Commit

Permalink
USB: gadget/printer, fix sleep inside atomic
Browse files Browse the repository at this point in the history
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: Jiri Slaby <jslaby@suse.cz>
Cc: Craig W. Nadler <craig@nadler.us>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Jiri Slaby authored and Greg Kroah-Hartman committed Jun 30, 2010
1 parent 1c81557 commit 10ca442
Showing 1 changed file with 16 additions and 16 deletions.
32 changes: 16 additions & 16 deletions drivers/usb/gadget/printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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);

Expand All @@ -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 */
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1594,14 +1594,14 @@ 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);

status = usb_gadget_unregister_driver(&printer_driver);
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);

0 comments on commit 10ca442

Please sign in to comment.