diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2013-10-04 12:07:00 +0100 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2013-10-12 12:07:11 +0100 |
commit | a95194569f697a6cc10d00f9b9b3d21b0b820520 (patch) | |
tree | b314a9155207e34ca0964d4ac3f127dcf2c87fd8 /drivers/iio/industrialio-buffer.c | |
parent | d2f0a48f36aea38e0a5c4b439d5d9c96aecabad9 (diff) | |
download | linux-a95194569f697a6cc10d00f9b9b3d21b0b820520.tar.gz linux-a95194569f697a6cc10d00f9b9b3d21b0b820520.tar.bz2 linux-a95194569f697a6cc10d00f9b9b3d21b0b820520.zip |
iio:buffer: Add proper locking for iio_update_buffers()
We need to make sure that in-kernel users of iio_update_buffers() do not race
against each other or against unregistration of the device. So we need to take
both the mlock and the info_exist_lock when calling iio_update_buffers() from a
in-kernel consumer.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/industrialio-buffer.c')
-rw-r--r-- | drivers/iio/industrialio-buffer.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 5a46c57a038b..d6a5455ae51a 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -509,7 +509,7 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev) indio_dev->setup_ops->postdisable(indio_dev); } -int iio_update_buffers(struct iio_dev *indio_dev, +static int __iio_update_buffers(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer) { @@ -674,6 +674,29 @@ error_ret: return ret; } + +int iio_update_buffers(struct iio_dev *indio_dev, + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer) +{ + int ret; + + mutex_lock(&indio_dev->info_exist_lock); + mutex_lock(&indio_dev->mlock); + + if (indio_dev->info == NULL) { + ret = -ENODEV; + goto out_unlock; + } + + ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer); + +out_unlock: + mutex_unlock(&indio_dev->mlock); + mutex_unlock(&indio_dev->info_exist_lock); + + return ret; +} EXPORT_SYMBOL_GPL(iio_update_buffers); ssize_t iio_buffer_store_enable(struct device *dev, @@ -699,10 +722,10 @@ ssize_t iio_buffer_store_enable(struct device *dev, goto done; if (requested_state) - ret = iio_update_buffers(indio_dev, + ret = __iio_update_buffers(indio_dev, indio_dev->buffer, NULL); else - ret = iio_update_buffers(indio_dev, + ret = __iio_update_buffers(indio_dev, NULL, indio_dev->buffer); if (ret < 0) |