Commit 8e695cdb authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

[PATCH] USB: cleanup of usblp

this fixes
-potential hang by disconnecting through usbfs
-kzalloc
-general cleanup
-micro optimisation in interrupt handlers

It compiles and I am printing.
Signed-off-by: default avatarOliver Neukum <oliver@neukum.name>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent abb02fdf
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com> # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com> # Copyright (c) 2001 David Paschal <paschal@rcsis.com>
* Copyright (c) 2006 Oliver Neukum <oliver@neukum.name>
* *
* USB Printer Device Class driver for USB printers and printer cables * USB Printer Device Class driver for USB printers and printer cables
* *
...@@ -273,13 +274,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs) ...@@ -273,13 +274,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs)
{ {
struct usblp *usblp = urb->context; struct usblp *usblp = urb->context;
if (!usblp || !usblp->dev || !usblp->used || !usblp->present) if (unlikely(!usblp || !usblp->dev || !usblp->used))
return; return;
if (unlikely(!usblp->present))
goto unplug;
if (unlikely(urb->status)) if (unlikely(urb->status))
warn("usblp%d: nonzero read/write bulk status received: %d", warn("usblp%d: nonzero read/write bulk status received: %d",
usblp->minor, urb->status); usblp->minor, urb->status);
usblp->rcomplete = 1; usblp->rcomplete = 1;
unplug:
wake_up_interruptible(&usblp->wait); wake_up_interruptible(&usblp->wait);
} }
...@@ -287,13 +291,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs) ...@@ -287,13 +291,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
{ {
struct usblp *usblp = urb->context; struct usblp *usblp = urb->context;
if (!usblp || !usblp->dev || !usblp->used || !usblp->present) if (unlikely(!usblp || !usblp->dev || !usblp->used))
return; return;
if (unlikely(!usblp->present))
goto unplug;
if (unlikely(urb->status)) if (unlikely(urb->status))
warn("usblp%d: nonzero read/write bulk status received: %d", warn("usblp%d: nonzero read/write bulk status received: %d",
usblp->minor, urb->status); usblp->minor, urb->status);
usblp->wcomplete = 1; usblp->wcomplete = 1;
unplug:
wake_up_interruptible(&usblp->wait); wake_up_interruptible(&usblp->wait);
} }
...@@ -627,9 +633,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -627,9 +633,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{ {
DECLARE_WAITQUEUE(wait, current);
struct usblp *usblp = file->private_data; struct usblp *usblp = file->private_data;
int timeout, err = 0, transfer_length = 0; int timeout, rv, err = 0, transfer_length = 0;
size_t writecount = 0; size_t writecount = 0;
while (writecount < count) { while (writecount < count) {
...@@ -641,24 +646,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t ...@@ -641,24 +646,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
} }
timeout = USBLP_WRITE_TIMEOUT; timeout = USBLP_WRITE_TIMEOUT;
add_wait_queue(&usblp->wait, &wait);
while ( 1==1 ) {
if (signal_pending(current)) { rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
remove_wait_queue(&usblp->wait, &wait); if (rv < 0)
return writecount ? writecount : -EINTR; return writecount ? writecount : -EINTR;
} }
set_current_state(TASK_INTERRUPTIBLE);
if (timeout && !usblp->wcomplete) {
timeout = schedule_timeout(timeout);
} else {
set_current_state(TASK_RUNNING);
break;
}
}
remove_wait_queue(&usblp->wait, &wait);
}
down (&usblp->sem); down (&usblp->sem);
if (!usblp->present) { if (!usblp->present) {
up (&usblp->sem); up (&usblp->sem);
...@@ -724,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t ...@@ -724,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{ {
struct usblp *usblp = file->private_data; struct usblp *usblp = file->private_data;
DECLARE_WAITQUEUE(wait, current); int rv;
if (!usblp->bidir) if (!usblp->bidir)
return -EINVAL; return -EINVAL;
...@@ -742,26 +734,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, ...@@ -742,26 +734,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
count = -EAGAIN; count = -EAGAIN;
goto done; goto done;
} }
up(&usblp->sem);
add_wait_queue(&usblp->wait, &wait); rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
while (1==1) { down(&usblp->sem);
if (signal_pending(current)) { if (rv < 0) {
count = -EINTR; count = -EINTR;
remove_wait_queue(&usblp->wait, &wait);
goto done; goto done;
} }
up (&usblp->sem);
set_current_state(TASK_INTERRUPTIBLE);
if (!usblp->rcomplete) {
schedule();
} else {
set_current_state(TASK_RUNNING);
down(&usblp->sem);
break;
}
down (&usblp->sem);
}
remove_wait_queue(&usblp->wait, &wait);
} }
if (!usblp->present) { if (!usblp->present) {
...@@ -874,11 +853,10 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -874,11 +853,10 @@ static int usblp_probe(struct usb_interface *intf,
/* Malloc and start initializing usblp structure so we can use it /* Malloc and start initializing usblp structure so we can use it
* directly. */ * directly. */
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) { if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
err("out of memory for usblp"); err("out of memory for usblp");
goto abort; goto abort;
} }
memset(usblp, 0, sizeof(struct usblp));
usblp->dev = dev; usblp->dev = dev;
init_MUTEX (&usblp->sem); init_MUTEX (&usblp->sem);
init_waitqueue_head(&usblp->wait); init_waitqueue_head(&usblp->wait);
...@@ -1214,10 +1192,9 @@ static int __init usblp_init(void) ...@@ -1214,10 +1192,9 @@ static int __init usblp_init(void)
{ {
int retval; int retval;
retval = usb_register(&usblp_driver); retval = usb_register(&usblp_driver);
if (retval) if (!retval)
goto out;
info(DRIVER_VERSION ": " DRIVER_DESC); info(DRIVER_VERSION ": " DRIVER_DESC);
out:
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment