Commit 69f894c3 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Jonathan Cameron

iio: ad9523: replace core mlock with local lock

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: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarAlexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent c344a327
...@@ -274,6 +274,15 @@ struct ad9523_state { ...@@ -274,6 +274,15 @@ struct ad9523_state {
unsigned long vco_out_freq[AD9523_NUM_CLK_SRC]; unsigned long vco_out_freq[AD9523_NUM_CLK_SRC];
unsigned char vco_out_map[AD9523_NUM_CHAN_ALT_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 * DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines. * transfer buffers to live in their own cache lines.
...@@ -500,6 +509,7 @@ static ssize_t ad9523_store(struct device *dev, ...@@ -500,6 +509,7 @@ static ssize_t ad9523_store(struct device *dev,
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct ad9523_state *st = iio_priv(indio_dev);
bool state; bool state;
int ret; int ret;
...@@ -510,7 +520,7 @@ static ssize_t ad9523_store(struct device *dev, ...@@ -510,7 +520,7 @@ static ssize_t ad9523_store(struct device *dev,
if (!state) if (!state)
return 0; return 0;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
switch ((u32)this_attr->address) { switch ((u32)this_attr->address) {
case AD9523_SYNC: case AD9523_SYNC:
ret = ad9523_sync(indio_dev); ret = ad9523_sync(indio_dev);
...@@ -521,7 +531,7 @@ static ssize_t ad9523_store(struct device *dev, ...@@ -521,7 +531,7 @@ static ssize_t ad9523_store(struct device *dev,
default: default:
ret = -ENODEV; ret = -ENODEV;
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -532,15 +542,16 @@ static ssize_t ad9523_show(struct device *dev, ...@@ -532,15 +542,16 @@ static ssize_t ad9523_show(struct device *dev,
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct ad9523_state *st = iio_priv(indio_dev);
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
ret = ad9523_read(indio_dev, AD9523_READBACK_0); ret = ad9523_read(indio_dev, AD9523_READBACK_0);
if (ret >= 0) { if (ret >= 0) {
ret = sprintf(buf, "%d\n", !!(ret & (1 << ret = sprintf(buf, "%d\n", !!(ret & (1 <<
(u32)this_attr->address))); (u32)this_attr->address)));
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret; return ret;
} }
...@@ -623,9 +634,9 @@ static int ad9523_read_raw(struct iio_dev *indio_dev, ...@@ -623,9 +634,9 @@ static int ad9523_read_raw(struct iio_dev *indio_dev,
unsigned int code; unsigned int code;
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
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);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -659,7 +670,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, ...@@ -659,7 +670,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev,
unsigned int reg; unsigned int reg;
int ret, tmp, code; int ret, tmp, code;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -705,7 +716,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, ...@@ -705,7 +716,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev,
ad9523_io_update(indio_dev); ad9523_io_update(indio_dev);
out: out:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret; return ret;
} }
...@@ -713,9 +724,10 @@ static int ad9523_reg_access(struct iio_dev *indio_dev, ...@@ -713,9 +724,10 @@ static int ad9523_reg_access(struct iio_dev *indio_dev,
unsigned int reg, unsigned int writeval, unsigned int reg, unsigned int writeval,
unsigned int *readval) unsigned int *readval)
{ {
struct ad9523_state *st = iio_priv(indio_dev);
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
if (readval == NULL) { if (readval == NULL) {
ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval); ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval);
ad9523_io_update(indio_dev); ad9523_io_update(indio_dev);
...@@ -728,7 +740,7 @@ static int ad9523_reg_access(struct iio_dev *indio_dev, ...@@ -728,7 +740,7 @@ static int ad9523_reg_access(struct iio_dev *indio_dev,
} }
out_unlock: out_unlock:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret; return ret;
} }
...@@ -967,6 +979,8 @@ static int ad9523_probe(struct spi_device *spi) ...@@ -967,6 +979,8 @@ static int ad9523_probe(struct spi_device *spi)
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->reg = devm_regulator_get(&spi->dev, "vcc"); st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) { if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg); ret = regulator_enable(st->reg);
......
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