aboutsummaryrefslogtreecommitdiffstats
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.c44
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;
}