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;
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) {
}
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);
dev->class_dev = csdev;
dev_set_drvdata(csdev, info);
+ /* Note: dev->mutex needs to be unlocked by the caller. */
return dev;
}
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);
}
}
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);