diff options
author | Oliver Neukum <neukum@fachschaft.cup.uni-muenchen.de> | 2006-01-07 15:35:20 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-31 20:23:37 -0500 |
commit | 8e695cdbffe66f5d3142a363f47053be9f83a90d (patch) | |
tree | 5bca03e23ce1a6ba89ac90da202958fb19881095 /drivers/usb | |
parent | abb02fdf83f981f2511b3772db6e106845c70ad9 (diff) |
[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: Oliver Neukum <oliver@neukum.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/class/usblp.c | 71 |
1 files changed, 24 insertions, 47 deletions
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index dba4cc026077..d34848ac30b0 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> |
8 | # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com> | 8 | # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com> |
9 | # Copyright (c) 2001 David Paschal <paschal@rcsis.com> | 9 | # Copyright (c) 2001 David Paschal <paschal@rcsis.com> |
10 | * Copyright (c) 2006 Oliver Neukum <oliver@neukum.name> | ||
10 | * | 11 | * |
11 | * USB Printer Device Class driver for USB printers and printer cables | 12 | * USB Printer Device Class driver for USB printers and printer cables |
12 | * | 13 | * |
@@ -273,13 +274,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs) | |||
273 | { | 274 | { |
274 | struct usblp *usblp = urb->context; | 275 | struct usblp *usblp = urb->context; |
275 | 276 | ||
276 | if (!usblp || !usblp->dev || !usblp->used || !usblp->present) | 277 | if (unlikely(!usblp || !usblp->dev || !usblp->used)) |
277 | return; | 278 | return; |
278 | 279 | ||
280 | if (unlikely(!usblp->present)) | ||
281 | goto unplug; | ||
279 | if (unlikely(urb->status)) | 282 | if (unlikely(urb->status)) |
280 | warn("usblp%d: nonzero read/write bulk status received: %d", | 283 | warn("usblp%d: nonzero read/write bulk status received: %d", |
281 | usblp->minor, urb->status); | 284 | usblp->minor, urb->status); |
282 | usblp->rcomplete = 1; | 285 | usblp->rcomplete = 1; |
286 | unplug: | ||
283 | wake_up_interruptible(&usblp->wait); | 287 | wake_up_interruptible(&usblp->wait); |
284 | } | 288 | } |
285 | 289 | ||
@@ -287,13 +291,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs) | |||
287 | { | 291 | { |
288 | struct usblp *usblp = urb->context; | 292 | struct usblp *usblp = urb->context; |
289 | 293 | ||
290 | if (!usblp || !usblp->dev || !usblp->used || !usblp->present) | 294 | if (unlikely(!usblp || !usblp->dev || !usblp->used)) |
291 | return; | 295 | return; |
292 | 296 | if (unlikely(!usblp->present)) | |
297 | goto unplug; | ||
293 | if (unlikely(urb->status)) | 298 | if (unlikely(urb->status)) |
294 | warn("usblp%d: nonzero read/write bulk status received: %d", | 299 | warn("usblp%d: nonzero read/write bulk status received: %d", |
295 | usblp->minor, urb->status); | 300 | usblp->minor, urb->status); |
296 | usblp->wcomplete = 1; | 301 | usblp->wcomplete = 1; |
302 | unplug: | ||
297 | wake_up_interruptible(&usblp->wait); | 303 | wake_up_interruptible(&usblp->wait); |
298 | } | 304 | } |
299 | 305 | ||
@@ -627,9 +633,8 @@ done: | |||
627 | 633 | ||
628 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 634 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
629 | { | 635 | { |
630 | DECLARE_WAITQUEUE(wait, current); | ||
631 | struct usblp *usblp = file->private_data; | 636 | struct usblp *usblp = file->private_data; |
632 | int timeout, err = 0, transfer_length = 0; | 637 | int timeout, rv, err = 0, transfer_length = 0; |
633 | size_t writecount = 0; | 638 | size_t writecount = 0; |
634 | 639 | ||
635 | while (writecount < count) { | 640 | while (writecount < count) { |
@@ -641,24 +646,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
641 | } | 646 | } |
642 | 647 | ||
643 | timeout = USBLP_WRITE_TIMEOUT; | 648 | timeout = USBLP_WRITE_TIMEOUT; |
644 | add_wait_queue(&usblp->wait, &wait); | ||
645 | while ( 1==1 ) { | ||
646 | 649 | ||
647 | if (signal_pending(current)) { | 650 | rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout); |
648 | remove_wait_queue(&usblp->wait, &wait); | 651 | if (rv < 0) |
649 | return writecount ? writecount : -EINTR; | 652 | return writecount ? writecount : -EINTR; |
650 | } | ||
651 | set_current_state(TASK_INTERRUPTIBLE); | ||
652 | if (timeout && !usblp->wcomplete) { | ||
653 | timeout = schedule_timeout(timeout); | ||
654 | } else { | ||
655 | set_current_state(TASK_RUNNING); | ||
656 | break; | ||
657 | } | ||
658 | } | ||
659 | remove_wait_queue(&usblp->wait, &wait); | ||
660 | } | 653 | } |
661 | |||
662 | down (&usblp->sem); | 654 | down (&usblp->sem); |
663 | if (!usblp->present) { | 655 | if (!usblp->present) { |
664 | up (&usblp->sem); | 656 | up (&usblp->sem); |
@@ -724,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
724 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 716 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
725 | { | 717 | { |
726 | struct usblp *usblp = file->private_data; | 718 | struct usblp *usblp = file->private_data; |
727 | DECLARE_WAITQUEUE(wait, current); | 719 | int rv; |
728 | 720 | ||
729 | if (!usblp->bidir) | 721 | if (!usblp->bidir) |
730 | return -EINVAL; | 722 | return -EINVAL; |
@@ -742,26 +734,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, | |||
742 | count = -EAGAIN; | 734 | count = -EAGAIN; |
743 | goto done; | 735 | goto done; |
744 | } | 736 | } |
745 | 737 | up(&usblp->sem); | |
746 | add_wait_queue(&usblp->wait, &wait); | 738 | rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); |
747 | while (1==1) { | 739 | down(&usblp->sem); |
748 | if (signal_pending(current)) { | 740 | if (rv < 0) { |
749 | count = -EINTR; | 741 | count = -EINTR; |
750 | remove_wait_queue(&usblp->wait, &wait); | 742 | goto done; |
751 | goto done; | ||
752 | } | ||
753 | up (&usblp->sem); | ||
754 | set_current_state(TASK_INTERRUPTIBLE); | ||
755 | if (!usblp->rcomplete) { | ||
756 | schedule(); | ||
757 | } else { | ||
758 | set_current_state(TASK_RUNNING); | ||
759 | down(&usblp->sem); | ||
760 | break; | ||
761 | } | ||
762 | down (&usblp->sem); | ||
763 | } | 743 | } |
764 | remove_wait_queue(&usblp->wait, &wait); | ||
765 | } | 744 | } |
766 | 745 | ||
767 | if (!usblp->present) { | 746 | if (!usblp->present) { |
@@ -874,11 +853,10 @@ static int usblp_probe(struct usb_interface *intf, | |||
874 | 853 | ||
875 | /* Malloc and start initializing usblp structure so we can use it | 854 | /* Malloc and start initializing usblp structure so we can use it |
876 | * directly. */ | 855 | * directly. */ |
877 | if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) { | 856 | if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { |
878 | err("out of memory for usblp"); | 857 | err("out of memory for usblp"); |
879 | goto abort; | 858 | goto abort; |
880 | } | 859 | } |
881 | memset(usblp, 0, sizeof(struct usblp)); | ||
882 | usblp->dev = dev; | 860 | usblp->dev = dev; |
883 | init_MUTEX (&usblp->sem); | 861 | init_MUTEX (&usblp->sem); |
884 | init_waitqueue_head(&usblp->wait); | 862 | init_waitqueue_head(&usblp->wait); |
@@ -1214,10 +1192,9 @@ static int __init usblp_init(void) | |||
1214 | { | 1192 | { |
1215 | int retval; | 1193 | int retval; |
1216 | retval = usb_register(&usblp_driver); | 1194 | retval = usb_register(&usblp_driver); |
1217 | if (retval) | 1195 | if (!retval) |
1218 | goto out; | 1196 | info(DRIVER_VERSION ": " DRIVER_DESC); |
1219 | info(DRIVER_VERSION ": " DRIVER_DESC); | 1197 | |
1220 | out: | ||
1221 | return retval; | 1198 | return retval; |
1222 | } | 1199 | } |
1223 | 1200 | ||