diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 558890ada0e5..c766b4a2630b 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -33,21 +33,20 @@ static DEFINE_MUTEX(init_usb_class_mutex); static int usb_open(struct inode *inode, struct file *file) { - int err = -ENODEV; + int err; const struct file_operations *new_fops; down_read(&minor_rwsem); new_fops = fops_get(usb_minors[iminor(inode)]); + up_read(&minor_rwsem); if (!new_fops) - goto done; + return -ENODEV; replace_fops(file, new_fops); /* Curiouser and curiouser... NULL ->open() as "no device" ? */ if (file->f_op->open) err = file->f_op->open(inode, file); - done: - up_read(&minor_rwsem); return err; } diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 2ca4e86c7b9f..3421fbc7c61d 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -488,31 +488,40 @@ static void free_imon_context(struct imon_context *ictx) dev_dbg(dev, "%s: iMON context freed\n", __func__); } +static struct imon_context *get_ictx_from_inode(struct inode *inode) +{ + struct usb_interface *interface; + struct imon_context *ictx = NULL; + int subminor; + + subminor = iminor(inode); + interface = usb_find_interface(&imon_driver, subminor); + if (!interface) { + pr_err("could not find interface for minor %d\n", subminor); + return NULL; + } + ictx = usb_get_intfdata(interface); + + if (!ictx) + pr_err("no context found for minor %d\n", subminor); + return ictx; +} + /* * Called when the Display device (e.g. /dev/lcd0) * is opened by the application. */ static int display_open(struct inode *inode, struct file *file) { - struct usb_interface *interface; struct imon_context *ictx = NULL; - int subminor; int retval = 0; /* prevent races with disconnect */ mutex_lock(&driver_lock); - subminor = iminor(inode); - interface = usb_find_interface(&imon_driver, subminor); - if (!interface) { - pr_err("could not find interface for minor %d\n", subminor); - retval = -ENODEV; - goto exit; - } - ictx = usb_get_intfdata(interface); + ictx = get_ictx_from_inode(inode); if (!ictx) { - pr_err("no context found for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -547,11 +556,14 @@ static int display_close(struct inode *inode, struct file *file) struct imon_context *ictx = NULL; int retval = 0; - ictx = file->private_data; + /* prevent races with disconnect */ + mutex_lock(&driver_lock); + + ictx = get_ictx_from_inode(inode); if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; + retval = -ENODEV; + goto exit; } mutex_lock(&ictx->lock); @@ -568,6 +580,9 @@ static int display_close(struct inode *inode, struct file *file) } mutex_unlock(&ictx->lock); + +exit: + mutex_unlock(&driver_lock); return retval; } @@ -584,6 +599,7 @@ static int send_packet(struct imon_context *ictx) int retval = 0; struct usb_ctrlrequest *control_req = NULL; + lockdep_assert_held_once(&ictx->lock); /* Check if we need to use control or interrupt urb */ if (!ictx->tx_control) { pipe = usb_sndintpipe(ictx->usbdev_intf0,