This is also part of a long term effort to make the use of mlock opaque and
single purpose.
This lock is required for accessing device registers. The device may be
accessed by multiple processes at the same time, and this can result in
inconsistent data, where one device reads data before the other one has
finished writing.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
unsigned long vco_out_freq[AD9523_NUM_CLK_SRC];
unsigned char vco_out_map[AD9523_NUM_CHAN_ALT_CLK_SRC];
unsigned long vco_out_freq[AD9523_NUM_CLK_SRC];
unsigned char vco_out_map[AD9523_NUM_CHAN_ALT_CLK_SRC];
+ /*
+ * Lock for accessing device registers. Some operations require
+ * multiple consecutive R/W operations, during which the device
+ * shouldn't be interrupted. The buffers are also shared across
+ * all operations so need to be protected on stand alone reads and
+ * writes.
+ */
+ struct mutex lock;
+
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ struct ad9523_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
switch ((u32)this_attr->address) {
case AD9523_SYNC:
ret = ad9523_sync(indio_dev);
switch ((u32)this_attr->address) {
case AD9523_SYNC:
ret = ad9523_sync(indio_dev);
default:
ret = -ENODEV;
}
default:
ret = -ENODEV;
}
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret ? ret : len;
}
return ret ? ret : len;
}
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ struct ad9523_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
ret = ad9523_read(indio_dev, AD9523_READBACK_0);
if (ret >= 0) {
ret = sprintf(buf, "%d\n", !!(ret & (1 <<
(u32)this_attr->address)));
}
ret = ad9523_read(indio_dev, AD9523_READBACK_0);
if (ret >= 0) {
ret = sprintf(buf, "%d\n", !!(ret & (1 <<
(u32)this_attr->address)));
}
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
unsigned int code;
int ret;
unsigned int code;
int ret;
- mutex_lock(&indio_dev->mlock);
ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
unsigned int reg;
int ret, tmp, code;
unsigned int reg;
int ret, tmp, code;
- mutex_lock(&indio_dev->mlock);
ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
if (ret < 0)
goto out;
ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
if (ret < 0)
goto out;
ad9523_io_update(indio_dev);
out:
ad9523_io_update(indio_dev);
out:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
unsigned int reg, unsigned int writeval,
unsigned int *readval)
{
unsigned int reg, unsigned int writeval,
unsigned int *readval)
{
+ struct ad9523_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
if (readval == NULL) {
ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval);
ad9523_io_update(indio_dev);
if (readval == NULL) {
ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval);
ad9523_io_update(indio_dev);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
st = iio_priv(indio_dev);
st = iio_priv(indio_dev);
+ mutex_init(&st->lock);
+
st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);