|
@@ -50,10 +50,12 @@ struct comedi_device *comedi_open(const char *filename)
|
|
|
if (!dev)
|
|
|
return NULL;
|
|
|
|
|
|
- if (dev->attached && try_module_get(dev->driver->module))
|
|
|
+ down_read(&dev->attach_lock);
|
|
|
+ if (dev->attached)
|
|
|
retval = dev;
|
|
|
else
|
|
|
retval = NULL;
|
|
|
+ up_read(&dev->attach_lock);
|
|
|
|
|
|
if (retval == NULL)
|
|
|
comedi_dev_put(dev);
|
|
@@ -62,13 +64,9 @@ struct comedi_device *comedi_open(const char *filename)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(comedi_open);
|
|
|
|
|
|
-int comedi_close(struct comedi_device *d)
|
|
|
+int comedi_close(struct comedi_device *dev)
|
|
|
{
|
|
|
- struct comedi_device *dev = (struct comedi_device *)d;
|
|
|
-
|
|
|
- module_put(dev->driver->module);
|
|
|
comedi_dev_put(dev);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(comedi_close);
|
|
@@ -78,7 +76,14 @@ static int comedi_do_insn(struct comedi_device *dev,
|
|
|
unsigned int *data)
|
|
|
{
|
|
|
struct comedi_subdevice *s;
|
|
|
- int ret = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock(&dev->mutex);
|
|
|
+
|
|
|
+ if (!dev->attached) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
|
|
|
/* a subdevice instruction */
|
|
|
if (insn->subdev >= dev->n_subdevices) {
|
|
@@ -125,6 +130,7 @@ static int comedi_do_insn(struct comedi_device *dev,
|
|
|
s->busy = NULL;
|
|
|
error:
|
|
|
|
|
|
+ mutex_unlock(&dev->mutex);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -174,9 +180,6 @@ int comedi_dio_bitfield2(struct comedi_device *dev, unsigned int subdev,
|
|
|
unsigned int shift;
|
|
|
int ret;
|
|
|
|
|
|
- if (subdev >= dev->n_subdevices)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
base_channel = CR_CHAN(base_channel);
|
|
|
n_chan = comedi_get_n_channels(dev, subdev);
|
|
|
if (base_channel >= n_chan)
|
|
@@ -216,23 +219,33 @@ int comedi_find_subdevice_by_type(struct comedi_device *dev, int type,
|
|
|
unsigned int subd)
|
|
|
{
|
|
|
struct comedi_subdevice *s;
|
|
|
-
|
|
|
- if (subd > dev->n_subdevices)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- for (; subd < dev->n_subdevices; subd++) {
|
|
|
- s = &dev->subdevices[subd];
|
|
|
- if (s->type == type)
|
|
|
- return subd;
|
|
|
- }
|
|
|
- return -1;
|
|
|
+ int ret = -ENODEV;
|
|
|
+
|
|
|
+ down_read(&dev->attach_lock);
|
|
|
+ if (dev->attached)
|
|
|
+ for (; subd < dev->n_subdevices; subd++) {
|
|
|
+ s = &dev->subdevices[subd];
|
|
|
+ if (s->type == type) {
|
|
|
+ ret = subd;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ up_read(&dev->attach_lock);
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(comedi_find_subdevice_by_type);
|
|
|
|
|
|
int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice)
|
|
|
{
|
|
|
- struct comedi_subdevice *s = &dev->subdevices[subdevice];
|
|
|
+ int n;
|
|
|
+
|
|
|
+ down_read(&dev->attach_lock);
|
|
|
+ if (!dev->attached || subdevice >= dev->n_subdevices)
|
|
|
+ n = 0;
|
|
|
+ else
|
|
|
+ n = dev->subdevices[subdevice].n_chan;
|
|
|
+ up_read(&dev->attach_lock);
|
|
|
|
|
|
- return s->n_chan;
|
|
|
+ return n;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(comedi_get_n_channels);
|