staging: comedi: pre-lock mutex on creation of comedi device
authorIan Abbott <abbotti@mev.co.uk>
Thu, 4 Apr 2013 13:58:51 +0000 (14:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Apr 2013 21:33:17 +0000 (14:33 -0700)
Return from `comedi_alloc_board_minor()` with the mutex of the created
`struct comedi_device` pre-locked.  This allows further initialization
by the caller without the worry of something getting in there first.

`comedi_auto_config()` no longer needs to check if the device is already
"attached" since whatever was trying to attach the device would need to
have locked the mutex first.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers.c

index f9d0a72..061b55b 100644 (file)
@@ -2274,6 +2274,7 @@ static void comedi_device_cleanup(struct comedi_device *dev)
        mutex_destroy(&dev->mutex);
 }
 
+/* Note: the ->mutex is pre-locked on successful return */
 struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
 {
        struct comedi_file_info *info;
@@ -2292,6 +2293,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
        info->device = dev;
        info->hardware_device = hardware_device;
        comedi_device_init(dev);
+       mutex_lock(&dev->mutex);
        spin_lock(&comedi_file_info_table_lock);
        for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) {
                if (comedi_file_info_table[i] == NULL) {
@@ -2301,6 +2303,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
        }
        spin_unlock(&comedi_file_info_table_lock);
        if (i == COMEDI_NUM_BOARD_MINORS) {
+               mutex_unlock(&dev->mutex);
                comedi_device_cleanup(dev);
                kfree(dev);
                kfree(info);
@@ -2314,6 +2317,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
                dev->class_dev = csdev;
        dev_set_drvdata(csdev, info);
 
+       /* Note: dev->mutex needs to be unlocked by the caller. */
        return dev;
 }
 
@@ -2485,6 +2489,9 @@ static int __init comedi_init(void)
                        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
                                                 COMEDI_NUM_MINORS);
                        return PTR_ERR(dev);
+               } else {
+                       /* comedi_alloc_board_minor() locked the mutex */
+                       mutex_unlock(&dev->mutex);
                }
        }
 
index 0b72af8..caadd3b 100644 (file)
@@ -429,11 +429,9 @@ int comedi_auto_config(struct device *hardware_device,
        comedi_dev = comedi_alloc_board_minor(hardware_device);
        if (IS_ERR(comedi_dev))
                return PTR_ERR(comedi_dev);
+       /* Note: comedi_alloc_board_minor() locked comedi_dev->mutex. */
 
-       mutex_lock(&comedi_dev->mutex);
-       if (comedi_dev->attached)
-               ret = -EBUSY;
-       else if (!try_module_get(driver->module))
+       if (!try_module_get(driver->module))
                ret = -EIO;
        else {
                comedi_set_hw_dev(comedi_dev, hardware_device);