diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/devio.c | 26 | ||||
-rw-r--r-- | drivers/usb/core/notify.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 |
3 files changed, 19 insertions, 11 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 32e03000420c..d8b0476237f3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -59,6 +59,9 @@ | |||
59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
60 | static struct class *usb_device_class; | 60 | static struct class *usb_device_class; |
61 | 61 | ||
62 | /* Mutual exclusion for removal, open, and release */ | ||
63 | DEFINE_MUTEX(usbfs_mutex); | ||
64 | |||
62 | struct async { | 65 | struct async { |
63 | struct list_head asynclist; | 66 | struct list_head asynclist; |
64 | struct dev_state *ps; | 67 | struct dev_state *ps; |
@@ -541,15 +544,13 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
541 | struct dev_state *ps; | 544 | struct dev_state *ps; |
542 | int ret; | 545 | int ret; |
543 | 546 | ||
544 | /* | 547 | /* Protect against simultaneous removal or release */ |
545 | * no locking necessary here, as chrdev_open has the kernel lock | 548 | mutex_lock(&usbfs_mutex); |
546 | * (still acquire the kernel lock for safety) | 549 | |
547 | */ | ||
548 | ret = -ENOMEM; | 550 | ret = -ENOMEM; |
549 | if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) | 551 | if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) |
550 | goto out_nolock; | 552 | goto out; |
551 | 553 | ||
552 | lock_kernel(); | ||
553 | ret = -ENOENT; | 554 | ret = -ENOENT; |
554 | /* check if we are called from a real node or usbfs */ | 555 | /* check if we are called from a real node or usbfs */ |
555 | if (imajor(inode) == USB_DEVICE_MAJOR) | 556 | if (imajor(inode) == USB_DEVICE_MAJOR) |
@@ -579,9 +580,8 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
579 | list_add_tail(&ps->list, &dev->filelist); | 580 | list_add_tail(&ps->list, &dev->filelist); |
580 | file->private_data = ps; | 581 | file->private_data = ps; |
581 | out: | 582 | out: |
582 | unlock_kernel(); | 583 | mutex_unlock(&usbfs_mutex); |
583 | out_nolock: | 584 | return ret; |
584 | return ret; | ||
585 | } | 585 | } |
586 | 586 | ||
587 | static int usbdev_release(struct inode *inode, struct file *file) | 587 | static int usbdev_release(struct inode *inode, struct file *file) |
@@ -591,7 +591,12 @@ static int usbdev_release(struct inode *inode, struct file *file) | |||
591 | unsigned int ifnum; | 591 | unsigned int ifnum; |
592 | 592 | ||
593 | usb_lock_device(dev); | 593 | usb_lock_device(dev); |
594 | |||
595 | /* Protect against simultaneous open */ | ||
596 | mutex_lock(&usbfs_mutex); | ||
594 | list_del_init(&ps->list); | 597 | list_del_init(&ps->list); |
598 | mutex_unlock(&usbfs_mutex); | ||
599 | |||
595 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); | 600 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
596 | ifnum++) { | 601 | ifnum++) { |
597 | if (test_bit(ifnum, &ps->ifclaimed)) | 602 | if (test_bit(ifnum, &ps->ifclaimed)) |
@@ -600,9 +605,8 @@ static int usbdev_release(struct inode *inode, struct file *file) | |||
600 | destroy_all_async(ps); | 605 | destroy_all_async(ps); |
601 | usb_unlock_device(dev); | 606 | usb_unlock_device(dev); |
602 | usb_put_dev(dev); | 607 | usb_put_dev(dev); |
603 | ps->dev = NULL; | ||
604 | kfree(ps); | 608 | kfree(ps); |
605 | return 0; | 609 | return 0; |
606 | } | 610 | } |
607 | 611 | ||
608 | static int proc_control(struct dev_state *ps, void __user *arg) | 612 | static int proc_control(struct dev_state *ps, void __user *arg) |
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index b042676af0a5..6b36897ca151 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c | |||
@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev) | |||
50 | 50 | ||
51 | void usb_notify_remove_device(struct usb_device *udev) | 51 | void usb_notify_remove_device(struct usb_device *udev) |
52 | { | 52 | { |
53 | /* Protect against simultaneous usbfs open */ | ||
54 | mutex_lock(&usbfs_mutex); | ||
53 | blocking_notifier_call_chain(&usb_notifier_list, | 55 | blocking_notifier_call_chain(&usb_notifier_list, |
54 | USB_DEVICE_REMOVE, udev); | 56 | USB_DEVICE_REMOVE, udev); |
57 | mutex_unlock(&usbfs_mutex); | ||
55 | } | 58 | } |
56 | 59 | ||
57 | void usb_notify_add_bus(struct usb_bus *ubus) | 60 | void usb_notify_add_bus(struct usb_bus *ubus) |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 49f69236b420..1217fbbe5829 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -59,6 +59,7 @@ static inline int is_active(struct usb_interface *f) | |||
59 | extern const char *usbcore_name; | 59 | extern const char *usbcore_name; |
60 | 60 | ||
61 | /* usbfs stuff */ | 61 | /* usbfs stuff */ |
62 | extern struct mutex usbfs_mutex; | ||
62 | extern struct usb_driver usbfs_driver; | 63 | extern struct usb_driver usbfs_driver; |
63 | extern struct file_operations usbfs_devices_fops; | 64 | extern struct file_operations usbfs_devices_fops; |
64 | extern struct file_operations usbfs_device_file_operations; | 65 | extern struct file_operations usbfs_device_file_operations; |