summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers.c')
-rw-r--r--drivers/staging/comedi/drivers.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index ba5d6d927a49..791a26bd5f63 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -38,6 +38,7 @@
#include "comedi_internal.h"
struct comedi_driver *comedi_drivers;
+DEFINE_MUTEX(comedi_drivers_list_lock);
int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
{
@@ -453,6 +454,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (dev->attached)
return -EBUSY;
+ mutex_lock(&comedi_drivers_list_lock);
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module))
continue;
@@ -473,7 +475,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
comedi_report_boards(driv);
module_put(driv->module);
}
- return -EIO;
+ ret = -EIO;
+ goto out;
}
if (driv->attach == NULL) {
/* driver does not support manual configuration */
@@ -481,7 +484,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
"driver '%s' does not support attach using comedi_config\n",
driv->driver_name);
module_put(driv->module);
- return -ENOSYS;
+ ret = -ENOSYS;
+ goto out;
}
/* initialize dev->driver here so
* comedi_error() can be called from attach */
@@ -496,6 +500,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
module_put(dev->driver->module);
}
/* On success, the driver module count has been incremented. */
+out:
+ mutex_unlock(&comedi_drivers_list_lock);
return ret;
}
@@ -552,8 +558,10 @@ EXPORT_SYMBOL_GPL(comedi_auto_unconfig);
int comedi_driver_register(struct comedi_driver *driver)
{
+ mutex_lock(&comedi_drivers_list_lock);
driver->next = comedi_drivers;
comedi_drivers = driver;
+ mutex_unlock(&comedi_drivers_list_lock);
return 0;
}
@@ -564,6 +572,20 @@ void comedi_driver_unregister(struct comedi_driver *driver)
struct comedi_driver *prev;
int i;
+ /* unlink the driver */
+ mutex_lock(&comedi_drivers_list_lock);
+ if (comedi_drivers == driver) {
+ comedi_drivers = driver->next;
+ } else {
+ for (prev = comedi_drivers; prev->next; prev = prev->next) {
+ if (prev->next == driver) {
+ prev->next = driver->next;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&comedi_drivers_list_lock);
+
/* check for devices using this driver */
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
struct comedi_device *dev = comedi_dev_from_minor(i);
@@ -581,17 +603,5 @@ void comedi_driver_unregister(struct comedi_driver *driver)
}
mutex_unlock(&dev->mutex);
}
-
- if (comedi_drivers == driver) {
- comedi_drivers = driver->next;
- return;
- }
-
- for (prev = comedi_drivers; prev->next; prev = prev->next) {
- if (prev->next == driver) {
- prev->next = driver->next;
- return;
- }
- }
}
EXPORT_SYMBOL_GPL(comedi_driver_unregister);