diff options
Diffstat (limited to 'drivers/usb/misc/ftdi-elan.c')
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index f21bf5160f83..32c47fbee288 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
48 | #include <linux/smp_lock.h> | ||
48 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
49 | #include <linux/usb.h> | 50 | #include <linux/usb.h> |
50 | #include <linux/workqueue.h> | 51 | #include <linux/workqueue.h> |
@@ -623,22 +624,30 @@ static void ftdi_elan_status_work(struct work_struct *work) | |||
623 | */ | 624 | */ |
624 | static int ftdi_elan_open(struct inode *inode, struct file *file) | 625 | static int ftdi_elan_open(struct inode *inode, struct file *file) |
625 | { | 626 | { |
626 | int subminor = iminor(inode); | 627 | int subminor; |
627 | struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver, | 628 | struct usb_interface *interface; |
628 | subminor); | 629 | |
630 | lock_kernel(); | ||
631 | subminor = iminor(inode); | ||
632 | interface = usb_find_interface(&ftdi_elan_driver, subminor); | ||
633 | |||
629 | if (!interface) { | 634 | if (!interface) { |
635 | unlock_kernel(); | ||
630 | printk(KERN_ERR "can't find device for minor %d\n", subminor); | 636 | printk(KERN_ERR "can't find device for minor %d\n", subminor); |
631 | return -ENODEV; | 637 | return -ENODEV; |
632 | } else { | 638 | } else { |
633 | struct usb_ftdi *ftdi = usb_get_intfdata(interface); | 639 | struct usb_ftdi *ftdi = usb_get_intfdata(interface); |
634 | if (!ftdi) { | 640 | if (!ftdi) { |
641 | unlock_kernel(); | ||
635 | return -ENODEV; | 642 | return -ENODEV; |
636 | } else { | 643 | } else { |
637 | if (down_interruptible(&ftdi->sw_lock)) { | 644 | if (down_interruptible(&ftdi->sw_lock)) { |
645 | unlock_kernel(); | ||
638 | return -EINTR; | 646 | return -EINTR; |
639 | } else { | 647 | } else { |
640 | ftdi_elan_get_kref(ftdi); | 648 | ftdi_elan_get_kref(ftdi); |
641 | file->private_data = ftdi; | 649 | file->private_data = ftdi; |
650 | unlock_kernel(); | ||
642 | return 0; | 651 | return 0; |
643 | } | 652 | } |
644 | } | 653 | } |