X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fusb%2Fclass%2Fusblp.c;h=292919d260a0744f0d997ee0859030ad6322d31d;hb=066202dd48cf3296b6cc22b5fcf89aef33fa0efc;hp=dba4cc0260770ebf8d6c39963cd8345c80a98b2a;hpb=944d79559d154c12becde0dab327016cf438f46c;p=linux-2.6 diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index dba4cc0260..292919d260 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -7,6 +7,7 @@ * Copyright (c) 2000 Vojtech Pavlik # Copyright (c) 2001 Pete Zaitcev # Copyright (c) 2001 David Paschal + * Copyright (c) 2006 Oliver Neukum * * USB Printer Device Class driver for USB printers and printer cables * @@ -54,6 +55,7 @@ #include #include #include +#include #undef DEBUG #include @@ -222,7 +224,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp); /* forward reference to make our lives easier */ static struct usb_driver usblp_driver; -static DECLARE_MUTEX(usblp_sem); /* locks the existence of usblp's */ +static DEFINE_MUTEX(usblp_mutex); /* locks the existence of usblp's */ /* * Functions for usblp control messages. @@ -273,13 +275,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs) { 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 +292,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs) { 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); } @@ -345,7 +352,7 @@ static int usblp_open(struct inode *inode, struct file *file) if (minor < 0) return -ENODEV; - down (&usblp_sem); + mutex_lock (&usblp_mutex); retval = -ENODEV; intf = usb_find_interface(&usblp_driver, minor); @@ -393,7 +400,7 @@ static int usblp_open(struct inode *inode, struct file *file) } } out: - up (&usblp_sem); + mutex_unlock (&usblp_mutex); return retval; } @@ -419,13 +426,13 @@ static int usblp_release(struct inode *inode, struct file *file) { struct usblp *usblp = file->private_data; - down (&usblp_sem); + mutex_lock (&usblp_mutex); usblp->used = 0; if (usblp->present) { usblp_unlink_urbs(usblp); } else /* finish cleanup from disconnect */ usblp_cleanup (usblp); - up (&usblp_sem); + mutex_unlock (&usblp_mutex); return 0; } @@ -627,9 +634,8 @@ done: 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; while (writecount < count) { @@ -641,24 +647,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t } 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; - } - } - remove_wait_queue(&usblp->wait, &wait); + rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout); + if (rv < 0) + return writecount ? writecount : -EINTR; } - down (&usblp->sem); if (!usblp->present) { up (&usblp->sem); @@ -724,7 +717,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) { struct usblp *usblp = file->private_data; - DECLARE_WAITQUEUE(wait, current); + int rv; if (!usblp->bidir) return -EINVAL; @@ -742,26 +735,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, 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); + up(&usblp->sem); + rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); + down(&usblp->sem); + if (rv < 0) { + count = -EINTR; + goto done; } - remove_wait_queue(&usblp->wait, &wait); } if (!usblp->present) { @@ -833,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product) return 0; } -static struct file_operations usblp_fops = { +static const struct file_operations usblp_fops = { .owner = THIS_MODULE, .read = usblp_read, .write = usblp_write, @@ -874,11 +854,10 @@ static int usblp_probe(struct usb_interface *intf, /* 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); @@ -1174,7 +1153,7 @@ static void usblp_disconnect(struct usb_interface *intf) device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - down (&usblp_sem); + mutex_lock (&usblp_mutex); down (&usblp->sem); usblp->present = 0; usb_set_intfdata (intf, NULL); @@ -1188,7 +1167,7 @@ static void usblp_disconnect(struct usb_interface *intf) if (!usblp->used) usblp_cleanup (usblp); - up (&usblp_sem); + mutex_unlock (&usblp_mutex); } static struct usb_device_id usblp_ids [] = { @@ -1214,10 +1193,9 @@ static int __init usblp_init(void) { 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; }