diff options
Diffstat (limited to 'drivers/staging/comedi/drivers.c')
-rw-r--r-- | drivers/staging/comedi/drivers.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index eefa62f42c0f..750a6ff3c03c 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -159,6 +159,8 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) int i; struct comedi_subdevice *s; + lockdep_assert_held(&dev->attach_lock); + lockdep_assert_held(&dev->mutex); if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; @@ -196,6 +198,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) void comedi_device_detach(struct comedi_device *dev) { + lockdep_assert_held(&dev->mutex); comedi_device_cancel_all(dev); down_write(&dev->attach_lock); dev->attached = false; @@ -394,11 +397,13 @@ unsigned int comedi_dio_update_state(struct comedi_subdevice *s, EXPORT_SYMBOL_GPL(comedi_dio_update_state); /** - * comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes + * comedi_bytes_per_scan_cmd() - Get length of asynchronous command "scan" in + * bytes * @s: COMEDI subdevice. + * @cmd: COMEDI command. * * Determines the overall scan length according to the subdevice type and the - * number of channels in the scan. + * number of channels in the scan for the specified command. * * For digital input, output or input/output subdevices, samples for * multiple channels are assumed to be packed into one or more unsigned @@ -408,9 +413,9 @@ EXPORT_SYMBOL_GPL(comedi_dio_update_state); * * Returns the overall scan length in bytes. */ -unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s) +unsigned int comedi_bytes_per_scan_cmd(struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - struct comedi_cmd *cmd = &s->async->cmd; unsigned int num_samples; unsigned int bits_per_sample; @@ -427,6 +432,29 @@ unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s) } return comedi_samples_to_bytes(s, num_samples); } +EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd); + +/** + * comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes + * @s: COMEDI subdevice. + * + * Determines the overall scan length according to the subdevice type and the + * number of channels in the scan for the current command. + * + * For digital input, output or input/output subdevices, samples for + * multiple channels are assumed to be packed into one or more unsigned + * short or unsigned int values according to the subdevice's %SDF_LSAMPL + * flag. For other types of subdevice, samples are assumed to occupy a + * whole unsigned short or unsigned int according to the %SDF_LSAMPL flag. + * + * Returns the overall scan length in bytes. + */ +unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + + return comedi_bytes_per_scan_cmd(s, cmd); +} EXPORT_SYMBOL_GPL(comedi_bytes_per_scan); static unsigned int __comedi_nscans_left(struct comedi_subdevice *s, @@ -618,6 +646,7 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev, unsigned int buf_size; int ret; + lockdep_assert_held(&dev->mutex); if ((s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) == 0) { dev_warn(dev->class_dev, "async subdevices must support SDF_CMD_READ or SDF_CMD_WRITE\n"); @@ -665,6 +694,7 @@ static int __comedi_device_postconfig(struct comedi_device *dev) int ret; int i; + lockdep_assert_held(&dev->mutex); if (!dev->insn_device_config) dev->insn_device_config = insn_device_inval; @@ -722,6 +752,7 @@ static int comedi_device_postconfig(struct comedi_device *dev) { int ret; + lockdep_assert_held(&dev->mutex); ret = __comedi_device_postconfig(dev); if (ret < 0) return ret; @@ -921,6 +952,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_driver *driv; int ret; + lockdep_assert_held(&dev->mutex); if (dev->attached) return -EBUSY; @@ -1028,18 +1060,19 @@ int comedi_auto_config(struct device *hardware_device, return PTR_ERR(dev); } /* Note: comedi_alloc_board_minor() locked dev->mutex. */ + lockdep_assert_held(&dev->mutex); dev->driver = driver; dev->board_name = dev->driver->driver_name; ret = driver->auto_attach(dev, context); if (ret >= 0) ret = comedi_device_postconfig(dev); - mutex_unlock(&dev->mutex); if (ret < 0) { dev_warn(hardware_device, "driver '%s' failed to auto-configure device.\n", driver->driver_name); + mutex_unlock(&dev->mutex); comedi_release_hardware_device(hardware_device); } else { /* @@ -1049,6 +1082,7 @@ int comedi_auto_config(struct device *hardware_device, dev_info(dev->class_dev, "driver '%s' has successfully auto-configured '%s'.\n", driver->driver_name, dev->board_name); + mutex_unlock(&dev->mutex); } return ret; } |