diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index b3a06f2dbad6e142ae25f567c57707b2febd7b85..7dc5a18e69d42bd4bd8e9df3d2458d368f769753 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -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);