Hi, does this fix the issues people have with that driver? I am not happy with the error handling, so this is not ready, but I'd like comments.
Regards Oliver --- linux-2.6.15-vanilla/drivers/usb/class/usblp.c 2006-01-03 04:21:10.000000000 +0100 +++ linux-2.6.15/drivers/usb/class/usblp.c 2006-01-08 22:25:35.000000000 +0100 @@ -7,6 +7,7 @@ * Copyright (c) 2000 Vojtech Pavlik <[EMAIL PROTECTED]> # Copyright (c) 2001 Pete Zaitcev <[EMAIL PROTECTED]> # Copyright (c) 2001 David Paschal <[EMAIL PROTECTED]> + * Copyright (c) 2006 Oliver Neukum <[EMAIL PROTECTED]> * * USB Printer Device Class driver for USB printers and printer cables * @@ -273,13 +274,16 @@ { struct usblp *usblp = urb->context; - if (!usblp || !usblp->dev || !usblp->used || !usblp->present) + if (unlikely(!usblp || !usblp->dev || !usblp->used)) return; + if (unlikely(!usblp->present)) + goto unplug; if (unlikely(urb->status)) warn("usblp%d: nonzero read/write bulk status received: %d", usblp->minor, urb->status); usblp->rcomplete = 1; +unplug: wake_up_interruptible(&usblp->wait); } @@ -287,13 +291,15 @@ { struct usblp *usblp = urb->context; - if (!usblp || !usblp->dev || !usblp->used || !usblp->present) + if (unlikely(!usblp || !usblp->dev || !usblp->used)) return; - + if (unlikely(!usblp->present)) + goto unplug; if (unlikely(urb->status)) warn("usblp%d: nonzero read/write bulk status received: %d", usblp->minor, urb->status); usblp->wcomplete = 1; +unplug: wake_up_interruptible(&usblp->wait); } @@ -627,43 +633,37 @@ 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; - int timeout, err = 0, transfer_length = 0; + int timeout, rv, err = 0, transfer_length = 0; size_t writecount = 0; + rv = down_interruptible (&usblp->sem); + if (rv) + return -EINTR; + while (writecount < count) { + + if (!usblp->present) { + count = -ENODEV; + goto out; + } + if (!usblp->wcomplete) { barrier(); if (file->f_flags & O_NONBLOCK) { writecount += transfer_length; - return writecount ? writecount : -EAGAIN; + count = writecount ? writecount : -EAGAIN; + goto out; } timeout = USBLP_WRITE_TIMEOUT; - add_wait_queue(&usblp->wait, &wait); - while ( 1==1 ) { - if (signal_pending(current)) { - remove_wait_queue(&usblp->wait, &wait); - return writecount ? writecount : -EINTR; - } - set_current_state(TASK_INTERRUPTIBLE); - if (timeout && !usblp->wcomplete) { - timeout = schedule_timeout(timeout); - } else { - set_current_state(TASK_RUNNING); - break; - } + rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout); + if (rv < 0) { + count = writecount ? writecount : -EINTR; } - remove_wait_queue(&usblp->wait, &wait); } - down (&usblp->sem); - if (!usblp->present) { - up (&usblp->sem); - return -ENODEV; - } if (usblp->writeurb->status != 0) { if (usblp->quirks & USBLP_QUIRK_BIDIR) { @@ -671,9 +671,9 @@ err("usblp%d: error %d writing to printer", usblp->minor, usblp->writeurb->status); err = usblp->writeurb->status; - } else + } else { err = usblp_check_status(usblp, err); - up (&usblp->sem); + } /* if the fault was due to disconnect, let khubd's * call to usblp_disconnect() grab usblp->sem ... @@ -688,7 +688,6 @@ */ writecount += transfer_length; if (writecount == count) { - up(&usblp->sem); break; } @@ -700,8 +699,8 @@ if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) { - up(&usblp->sem); - return writecount ? writecount : -EFAULT; + count = writecount ? writecount : -EFAULT; + goto out; } usblp->writeurb->dev = usblp->dev; @@ -712,24 +711,26 @@ count = -EIO; else count = writecount ? writecount : -ENOMEM; - up (&usblp->sem); break; } - up (&usblp->sem); } - +out: + up (&usblp->sem); return count; } static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct usblp *usblp = file->private_data; - DECLARE_WAITQUEUE(wait, current); + int rv; if (!usblp->bidir) return -EINVAL; - down (&usblp->sem); + rv = down_interruptible (&usblp->sem); + if (rv) + return -EINTR; + if (!usblp->present) { count = -ENODEV; goto done; @@ -742,26 +743,11 @@ count = -EAGAIN; goto done; } - - add_wait_queue(&usblp->wait, &wait); - while (1==1) { - if (signal_pending(current)) { - count = -EINTR; - remove_wait_queue(&usblp->wait, &wait); - 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); + rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); + if (rv < 0) { + count = -EINTR; + goto done; } - remove_wait_queue(&usblp->wait, &wait); } if (!usblp->present) { @@ -859,11 +845,10 @@ /* Malloc and start initializing usblp structure so we can use it * directly. */ - if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) { + if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { err("out of memory for usblp"); goto abort; } - memset(usblp, 0, sizeof(struct usblp)); usblp->dev = dev; init_MUTEX (&usblp->sem); init_waitqueue_head(&usblp->wait); @@ -1151,22 +1136,22 @@ usb_deregister_dev(intf, &usblp_class); - if (!usblp || !usblp->dev) { - err("bogus disconnect"); - BUG (); - } + BUG_ON(!usblp || !usblp->dev); - down (&usblp_sem); - down (&usblp->sem); + down (&usblp_sem); /* guard against open */ + + /* mark the device as gone without further locking */ usblp->present = 0; + down (&usblp->sem); usb_set_intfdata (intf, NULL); + up (&usblp->sem); + /* now any method under usblp->sem can check usblp->present */ usblp_unlink_urbs(usblp); usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, usblp->writebuf, usblp->writeurb->transfer_dma); usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, usblp->readbuf, usblp->readurb->transfer_dma); - up (&usblp->sem); if (!usblp->used) usblp_cleanup (usblp); @@ -1197,10 +1182,9 @@ { int retval; retval = usb_register(&usblp_driver); - if (retval) - goto out; - info(DRIVER_VERSION ": " DRIVER_DESC); -out: + if (!retval) + info(DRIVER_VERSION ": " DRIVER_DESC); + return retval; } ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel