diff options
Diffstat (limited to 'drivers/usb/core/devio.c')
| -rw-r--r-- | drivers/usb/core/devio.c | 93 | 
1 files changed, 25 insertions, 68 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8df4b76465a..e0f107948eb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -333,17 +333,14 @@ static struct async *async_getcompleted(struct dev_state *ps)  static struct async *async_getpending(struct dev_state *ps,  					     void __user *userurb)  { -	unsigned long flags;  	struct async *as; -	spin_lock_irqsave(&ps->lock, flags);  	list_for_each_entry(as, &ps->async_pending, asynclist)  		if (as->userurb == userurb) {  			list_del_init(&as->asynclist); -			spin_unlock_irqrestore(&ps->lock, flags);  			return as;  		} -	spin_unlock_irqrestore(&ps->lock, flags); +  	return NULL;  } @@ -398,6 +395,7 @@ static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr)  __releases(ps->lock)  __acquires(ps->lock)  { +	struct urb *urb;  	struct async *as;  	/* Mark all the pending URBs that match bulk_addr, up to but not @@ -420,8 +418,11 @@ __acquires(ps->lock)  	list_for_each_entry(as, &ps->async_pending, asynclist) {  		if (as->bulk_status == AS_UNLINK) {  			as->bulk_status = 0;		/* Only once */ +			urb = as->urb; +			usb_get_urb(urb);  			spin_unlock(&ps->lock);		/* Allow completions */ -			usb_unlink_urb(as->urb); +			usb_unlink_urb(urb); +			usb_put_urb(urb);  			spin_lock(&ps->lock);  			goto rescan;  		} @@ -472,6 +473,7 @@ static void async_completed(struct urb *urb)  static void destroy_async(struct dev_state *ps, struct list_head *list)  { +	struct urb *urb;  	struct async *as;  	unsigned long flags; @@ -479,10 +481,13 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)  	while (!list_empty(list)) {  		as = list_entry(list->next, struct async, asynclist);  		list_del_init(&as->asynclist); +		urb = as->urb; +		usb_get_urb(urb);  		/* drop the spinlock so the completion handler can run */  		spin_unlock_irqrestore(&ps->lock, flags); -		usb_kill_urb(as->urb); +		usb_kill_urb(urb); +		usb_put_urb(urb);  		spin_lock_irqsave(&ps->lock, flags);  	}  	spin_unlock_irqrestore(&ps->lock, flags); @@ -727,17 +732,6 @@ static int usbdev_open(struct inode *inode, struct file *file)  	if (imajor(inode) == USB_DEVICE_MAJOR)  		dev = usbdev_lookup_by_devt(inode->i_rdev); -#ifdef CONFIG_USB_DEVICEFS -	/* procfs file */ -	if (!dev) { -		dev = inode->i_private; -		if (dev && dev->usbfs_dentry && -					dev->usbfs_dentry->d_inode == inode) -			usb_get_dev(dev); -		else -			dev = NULL; -	} -#endif  	mutex_unlock(&usbfs_mutex);  	if (!dev) @@ -1410,12 +1404,24 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)  static int proc_unlinkurb(struct dev_state *ps, void __user *arg)  { +	struct urb *urb;  	struct async *as; +	unsigned long flags; +	spin_lock_irqsave(&ps->lock, flags);  	as = async_getpending(ps, arg); -	if (!as) +	if (!as) { +		spin_unlock_irqrestore(&ps->lock, flags);  		return -EINVAL; -	usb_kill_urb(as->urb); +	} + +	urb = as->urb; +	usb_get_urb(urb); +	spin_unlock_irqrestore(&ps->lock, flags); + +	usb_kill_urb(urb); +	usb_put_urb(urb); +  	return 0;  } @@ -2062,44 +2068,13 @@ static void usbdev_remove(struct usb_device *udev)  	}  } -#ifdef CONFIG_USB_DEVICE_CLASS -static struct class *usb_classdev_class; - -static int usb_classdev_add(struct usb_device *dev) -{ -	struct device *cldev; - -	cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, -			      NULL, "usbdev%d.%d", dev->bus->busnum, -			      dev->devnum); -	if (IS_ERR(cldev)) -		return PTR_ERR(cldev); -	dev->usb_classdev = cldev; -	return 0; -} - -static void usb_classdev_remove(struct usb_device *dev) -{ -	if (dev->usb_classdev) -		device_unregister(dev->usb_classdev); -} - -#else -#define usb_classdev_add(dev)		0 -#define usb_classdev_remove(dev)	do {} while (0) - -#endif -  static int usbdev_notify(struct notifier_block *self,  			       unsigned long action, void *dev)  {  	switch (action) {  	case USB_DEVICE_ADD: -		if (usb_classdev_add(dev)) -			return NOTIFY_BAD;  		break;  	case USB_DEVICE_REMOVE: -		usb_classdev_remove(dev);  		usbdev_remove(dev);  		break;  	} @@ -2129,21 +2104,6 @@ int __init usb_devio_init(void)  		       USB_DEVICE_MAJOR);  		goto error_cdev;  	} -#ifdef CONFIG_USB_DEVICE_CLASS -	usb_classdev_class = class_create(THIS_MODULE, "usb_device"); -	if (IS_ERR(usb_classdev_class)) { -		printk(KERN_ERR "Unable to register usb_device class\n"); -		retval = PTR_ERR(usb_classdev_class); -		cdev_del(&usb_device_cdev); -		usb_classdev_class = NULL; -		goto out; -	} -	/* devices of this class shadow the major:minor of their parent -	 * device, so clear ->dev_kobj to prevent adding duplicate entries -	 * to /sys/dev -	 */ -	usb_classdev_class->dev_kobj = NULL; -#endif  	usb_register_notify(&usbdev_nb);  out:  	return retval; @@ -2156,9 +2116,6 @@ error_cdev:  void usb_devio_cleanup(void)  {  	usb_unregister_notify(&usbdev_nb); -#ifdef CONFIG_USB_DEVICE_CLASS -	class_destroy(usb_classdev_class); -#endif  	cdev_del(&usb_device_cdev);  	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);  }  |