[PATCH 14/15] iio: health: max30102: do not use internal iio_dev lock

Nuno Sá
2022-09-20T11:37:24Z

The pattern used in this device does not quite fit in the
iio_device_claim_direct_mode() typical usage. In this case,
iio_buffer_enabled() was being used not to prevent the raw access
but to decide whether or not the device needs to be powered on before.
If buffering, then the device is already on. To guarantee the same
behavior, a combination of locks is being used:

1. Use iio_device_claim_direct_mode() to check if direct mode can be
claimed and if we can, then we keep it until the reading is done (which
also means the device will be powered on and off);
2. If already buffering, we need to make sure that buffering is not
disabled (and hence, powering off the device) while doing a raw read. For
that, we can make use of the local lock that already exists.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
drivers/iio/health/max30102.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index abbcef563807..e984c78b99f6 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -227,9 +227,20 @@ static int max30102_buffer_postenable(struct iio_dev *indio_dev)
static int max30102_buffer_predisable(struct iio_dev *indio_dev)
{
struct max30102_data *data = iio_priv(indio_dev);
+ int ret;
+
+ /*
+ * As stated in the comment in the read_raw() function, temperature
+ * can only be acquired if the engine is running. As such the mutex
+ * is used to make sure we do not power down while doing a temperature
+ * reading.
+ */
+ mutex_lock(&data->lock);
+ ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
+ false);
+ mutex_unlock(&data->lock);

- return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
- false);
+ return ret;
}

static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
@@ -477,12 +488,14 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
* Temperature reading can only be acquired when not in
* shutdown; leave shutdown briefly when buffer not running
*/
- mutex_lock(&indio_dev->mlock);
- if (!iio_buffer_enabled(indio_dev))
+ if (!iio_device_claim_direct_mode(indio_dev)) {
ret = max30102_get_temp(data, val, true);
- else
+ iio_device_release_direct_mode(indio_dev);
+ } else {
+ mutex_lock(&data->lock);
ret = max30102_get_temp(data, val, false);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&data->lock);
+ }
if (ret)
return ret;

--
2.37.3