Commit 7f4656c5 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

staging: comedi: get mutex before subdevice in attribute functions

The comedi device attribute functions such as
`show_read_buffer_kb()` or `show_write_buffer_kb()` call
`comedi_read_subdevice()` or `comedi_write_subdevice()` without
acquiring the comedi device's mutex first, although the functions do
acquire the mutex afterwards.  Change them to acquire the mutex first.
This is consistent with most of the comedi device file operation
functions (apart from `comedi_read()` and `comedi_write()` which
probably need looking at).

Despite the use of the mutex, there are still race conditions as the
`struct comedi_file_info *info` variable value set before acquiring the
mutex could be stale after acquiring the mutex.  This problem will be
dealt with once reference counting has been implemented for the comedi
devices.

This patch also adds local variable `struct comedi_device *dev` to the
functions to reduce the use of the `info` variable a little bit.
Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Reviewed-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7a4e5a9f
...@@ -276,13 +276,16 @@ static ssize_t show_max_read_buffer_kb(struct device *csdev, ...@@ -276,13 +276,16 @@ static ssize_t show_max_read_buffer_kb(struct device *csdev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_read_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size = 0; unsigned int size = 0;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_read_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
size = s->async->max_bufsize / 1024; size = s->async->max_bufsize / 1024;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return snprintf(buf, PAGE_SIZE, "%i\n", size); return snprintf(buf, PAGE_SIZE, "%i\n", size);
} }
...@@ -292,7 +295,8 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev, ...@@ -292,7 +295,8 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_read_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size; unsigned int size;
int err; int err;
...@@ -303,12 +307,14 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev, ...@@ -303,12 +307,14 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev,
return -EINVAL; return -EINVAL;
size *= 1024; size *= 1024;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_read_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
s->async->max_bufsize = size; s->async->max_bufsize = size;
else else
err = -EINVAL; err = -EINVAL;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return err ? err : count; return err ? err : count;
} }
...@@ -317,13 +323,16 @@ static ssize_t show_read_buffer_kb(struct device *csdev, ...@@ -317,13 +323,16 @@ static ssize_t show_read_buffer_kb(struct device *csdev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_read_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size = 0; unsigned int size = 0;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_read_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
size = s->async->prealloc_bufsz / 1024; size = s->async->prealloc_bufsz / 1024;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return snprintf(buf, PAGE_SIZE, "%i\n", size); return snprintf(buf, PAGE_SIZE, "%i\n", size);
} }
...@@ -333,7 +342,8 @@ static ssize_t store_read_buffer_kb(struct device *csdev, ...@@ -333,7 +342,8 @@ static ssize_t store_read_buffer_kb(struct device *csdev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_read_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size; unsigned int size;
int err; int err;
...@@ -344,12 +354,14 @@ static ssize_t store_read_buffer_kb(struct device *csdev, ...@@ -344,12 +354,14 @@ static ssize_t store_read_buffer_kb(struct device *csdev,
return -EINVAL; return -EINVAL;
size *= 1024; size *= 1024;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_read_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
err = resize_async_buffer(info->device, s, s->async, size); err = resize_async_buffer(dev, s, s->async, size);
else else
err = -EINVAL; err = -EINVAL;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return err ? err : count; return err ? err : count;
} }
...@@ -359,13 +371,16 @@ static ssize_t show_max_write_buffer_kb(struct device *csdev, ...@@ -359,13 +371,16 @@ static ssize_t show_max_write_buffer_kb(struct device *csdev,
char *buf) char *buf)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_write_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size = 0; unsigned int size = 0;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_write_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
size = s->async->max_bufsize / 1024; size = s->async->max_bufsize / 1024;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return snprintf(buf, PAGE_SIZE, "%i\n", size); return snprintf(buf, PAGE_SIZE, "%i\n", size);
} }
...@@ -375,7 +390,8 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev, ...@@ -375,7 +390,8 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_write_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size; unsigned int size;
int err; int err;
...@@ -386,12 +402,14 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev, ...@@ -386,12 +402,14 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev,
return -EINVAL; return -EINVAL;
size *= 1024; size *= 1024;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_write_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
s->async->max_bufsize = size; s->async->max_bufsize = size;
else else
err = -EINVAL; err = -EINVAL;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return err ? err : count; return err ? err : count;
} }
...@@ -400,13 +418,16 @@ static ssize_t show_write_buffer_kb(struct device *csdev, ...@@ -400,13 +418,16 @@ static ssize_t show_write_buffer_kb(struct device *csdev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_write_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size = 0; unsigned int size = 0;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_write_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
size = s->async->prealloc_bufsz / 1024; size = s->async->prealloc_bufsz / 1024;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return snprintf(buf, PAGE_SIZE, "%i\n", size); return snprintf(buf, PAGE_SIZE, "%i\n", size);
} }
...@@ -416,7 +437,8 @@ static ssize_t store_write_buffer_kb(struct device *csdev, ...@@ -416,7 +437,8 @@ static ssize_t store_write_buffer_kb(struct device *csdev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct comedi_file_info *info = dev_get_drvdata(csdev); struct comedi_file_info *info = dev_get_drvdata(csdev);
struct comedi_subdevice *s = comedi_write_subdevice(info); struct comedi_device *dev;
struct comedi_subdevice *s;
unsigned int size; unsigned int size;
int err; int err;
...@@ -427,12 +449,14 @@ static ssize_t store_write_buffer_kb(struct device *csdev, ...@@ -427,12 +449,14 @@ static ssize_t store_write_buffer_kb(struct device *csdev,
return -EINVAL; return -EINVAL;
size *= 1024; size *= 1024;
mutex_lock(&info->device->mutex); dev = info->device;
mutex_lock(&dev->mutex);
s = comedi_write_subdevice(info);
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
err = resize_async_buffer(info->device, s, s->async, size); err = resize_async_buffer(dev, s, s->async, size);
else else
err = -EINVAL; err = -EINVAL;
mutex_unlock(&info->device->mutex); mutex_unlock(&dev->mutex);
return err ? err : count; return err ? err : count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment