Commit 984fb244 authored by Narcisa Ana Maria Vasile's avatar Narcisa Ana Maria Vasile Committed by Jonathan Cameron

staging: iio: ad5933: Protect DIRECT mode using claim/release helpers

This device operates in DIRECT_MODE and BUFFER_HARDWARE mode.
Replace usages of iio_dev->mlock with iio_device_{claim|release}_direct_mode()
helper functions to guarantee DIRECT mode and consequently protect
BUFFER mode too.

Add and use a device private lock to protect against conflicting access of the
state data.
This helps with IIO subsystem redefining iio_dev->mlock to be used by
the IIO core only for protecting device operating mode changes.
ie. Changes between INDIO_DIRECT_MODE, INDIO_BUFFER_* modes.

Protect changing of attributes inside ad5933_store(). Attributes
can no longer be changed while in buffered mode.

Remove lock from ad5933_work() because buffer mode should be enabled
when we reach this, and claiming DIRECT mode in all the other places
should protect it.
Signed-off-by: default avatarNarcisa Ana Maria Vasile <narcisaanamaria12@gmail.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent a9e9c715
...@@ -98,6 +98,7 @@ struct ad5933_state { ...@@ -98,6 +98,7 @@ struct ad5933_state {
struct i2c_client *client; struct i2c_client *client;
struct regulator *reg; struct regulator *reg;
struct delayed_work work; struct delayed_work work;
struct mutex lock; /* Protect sensor state */
unsigned long mclk_hz; unsigned long mclk_hz;
unsigned char ctrl_hb; unsigned char ctrl_hb;
unsigned char ctrl_lb; unsigned char ctrl_lb;
...@@ -306,9 +307,11 @@ static ssize_t ad5933_show_frequency(struct device *dev, ...@@ -306,9 +307,11 @@ static ssize_t ad5933_show_frequency(struct device *dev,
u8 d8[4]; u8 d8[4];
} dat; } dat;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]); ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]);
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -338,9 +341,11 @@ static ssize_t ad5933_store_frequency(struct device *dev, ...@@ -338,9 +341,11 @@ static ssize_t ad5933_store_frequency(struct device *dev,
if (val > AD5933_MAX_OUTPUT_FREQ_Hz) if (val > AD5933_MAX_OUTPUT_FREQ_Hz)
return -EINVAL; return -EINVAL;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
ret = ad5933_set_freq(st, this_attr->address, val); ret = ad5933_set_freq(st, this_attr->address, val);
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -364,7 +369,7 @@ static ssize_t ad5933_show(struct device *dev, ...@@ -364,7 +369,7 @@ static ssize_t ad5933_show(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret = 0, len = 0; int ret = 0, len = 0;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
switch ((u32)this_attr->address) { switch ((u32)this_attr->address) {
case AD5933_OUT_RANGE: case AD5933_OUT_RANGE:
len = sprintf(buf, "%u\n", len = sprintf(buf, "%u\n",
...@@ -393,7 +398,7 @@ static ssize_t ad5933_show(struct device *dev, ...@@ -393,7 +398,7 @@ static ssize_t ad5933_show(struct device *dev,
ret = -EINVAL; ret = -EINVAL;
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -415,7 +420,10 @@ static ssize_t ad5933_store(struct device *dev, ...@@ -415,7 +420,10 @@ static ssize_t ad5933_store(struct device *dev,
return ret; return ret;
} }
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
mutex_lock(&st->lock);
switch ((u32)this_attr->address) { switch ((u32)this_attr->address) {
case AD5933_OUT_RANGE: case AD5933_OUT_RANGE:
ret = -EINVAL; ret = -EINVAL;
...@@ -465,7 +473,8 @@ static ssize_t ad5933_store(struct device *dev, ...@@ -465,7 +473,8 @@ static ssize_t ad5933_store(struct device *dev,
ret = -EINVAL; ret = -EINVAL;
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -532,11 +541,9 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, ...@@ -532,11 +541,9 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
ret = -EBUSY; return ret;
goto out;
}
ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP); ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -549,7 +556,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, ...@@ -549,7 +556,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
2, (u8 *)&dat); 2, (u8 *)&dat);
if (ret < 0) if (ret < 0)
goto out; goto out;
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
*val = sign_extend32(be16_to_cpu(dat), 13); *val = sign_extend32(be16_to_cpu(dat), 13);
return IIO_VAL_INT; return IIO_VAL_INT;
...@@ -561,7 +568,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, ...@@ -561,7 +568,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
return -EINVAL; return -EINVAL;
out: out:
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
return ret; return ret;
} }
...@@ -657,18 +664,17 @@ static void ad5933_work(struct work_struct *work) ...@@ -657,18 +664,17 @@ static void ad5933_work(struct work_struct *work)
unsigned char status; unsigned char status;
int ret; int ret;
mutex_lock(&indio_dev->mlock);
if (st->state == AD5933_CTRL_INIT_START_FREQ) { if (st->state == AD5933_CTRL_INIT_START_FREQ) {
/* start sweep */ /* start sweep */
ad5933_cmd(st, AD5933_CTRL_START_SWEEP); ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
st->state = AD5933_CTRL_START_SWEEP; st->state = AD5933_CTRL_START_SWEEP;
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
goto out; return;
} }
ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
if (ret) if (ret)
goto out; return;
if (status & AD5933_STAT_DATA_VALID) { if (status & AD5933_STAT_DATA_VALID) {
int scan_count = bitmap_weight(indio_dev->active_scan_mask, int scan_count = bitmap_weight(indio_dev->active_scan_mask,
...@@ -678,7 +684,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -678,7 +684,7 @@ static void ad5933_work(struct work_struct *work)
AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
scan_count * 2, (u8 *)buf); scan_count * 2, (u8 *)buf);
if (ret) if (ret)
goto out; return;
if (scan_count == 2) { if (scan_count == 2) {
val[0] = be16_to_cpu(buf[0]); val[0] = be16_to_cpu(buf[0]);
...@@ -690,7 +696,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -690,7 +696,7 @@ static void ad5933_work(struct work_struct *work)
} else { } else {
/* no data available - try again later */ /* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
goto out; return;
} }
if (status & AD5933_STAT_SWEEP_DONE) { if (status & AD5933_STAT_SWEEP_DONE) {
...@@ -703,8 +709,6 @@ static void ad5933_work(struct work_struct *work) ...@@ -703,8 +709,6 @@ static void ad5933_work(struct work_struct *work)
ad5933_cmd(st, AD5933_CTRL_INC_FREQ); ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
} }
out:
mutex_unlock(&indio_dev->mlock);
} }
static int ad5933_probe(struct i2c_client *client, static int ad5933_probe(struct i2c_client *client,
...@@ -723,6 +727,8 @@ static int ad5933_probe(struct i2c_client *client, ...@@ -723,6 +727,8 @@ static int ad5933_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
st->client = client; st->client = client;
mutex_init(&st->lock);
if (!pdata) if (!pdata)
pdata = &ad5933_default_pdata; pdata = &ad5933_default_pdata;
......
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