[PATCH v2 05/17] iio: accel: bmc150: Discard pm_runtime_put_autosuspend() return values

From: Brian Norris

Date: Wed Oct 21 2026 - 20:02:59 EST


This driver propagates the return value of pm_runtime_put_autosuspend(),
which is not particularly useful.

Returning an error code from pm_runtime_put_autosuspend() merely means
that it has not queued up a timer or work item to check whether or not
the device can be suspended and there are many perfectly valid
situations in which that can happen, like after writing "on" to the
device's runtime PM "control" attribute in sysfs for one example.

For this reason, modify this driver to simply discard the
pm_runtime_put_autosuspend() return value, and inline the pm_runtime
helper, now that it behaves the same with and without CONFIG_PM.

While at it, I notice that bmc150_accel_set_interrupt() mismanages the
reference counts. It should only drop a reference after it's done
touching the hardware in question. Adjust the local &intr->users
reference count alongside the error handling too, to ensure proper
balance.

This will facilitate a planned change of the
pm_runtime_put_autosuspend() return type to void in the future, similar
to commit 3afd8df02433 ("PM: runtime: Change pm_runtime_put() return
type to void").

Signed-off-by: Brian Norris <briannorris@xxxxxxxxxxxx>
---

Changes in v2:
* Split iio patch into per-driver patches
* Inlining
* Refcount ordering

drivers/iio/accel/bmc150-accel-core.c | 75 +++++++++++----------------
1 file changed, 31 insertions(+), 44 deletions(-)

diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 46bb36d9366e..9ad6429fb584 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -326,29 +326,6 @@ static int bmc150_accel_get_startup_times(struct bmc150_accel_data *data)

return BMC150_ACCEL_MAX_STARTUP_TIME_MS;
}
-
-static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
-{
- struct device *dev = regmap_get_device(data->regmap);
- int ret;
-
- if (on)
- ret = pm_runtime_resume_and_get(dev);
- else
- ret = pm_runtime_put_autosuspend(dev);
- if (ret < 0) {
- dev_err(dev,
- "Failed: %s for %d\n", __func__, on);
- return ret;
- }
-
- return 0;
-}
-#else
-static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
-{
- return 0;
-}
#endif

#ifdef CONFIG_ACPI
@@ -530,24 +507,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
if (state) {
if (atomic_inc_return(&intr->users) > 1)
return 0;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0) {
+ dev_err(dev, "failed to resume: %d\n", ret);
+ atomic_dec(&intr->users);
+ return ret;
+ }
} else {
if (atomic_dec_return(&intr->users) > 0)
return 0;
}

- /*
- * We will expect the enable and disable to do operation in reverse
- * order. This will happen here anyway, as our resume operation uses
- * sync mode runtime pm calls. The suspend operation will be delayed
- * by autosuspend delay.
- * So the disable operation will still happen in reverse order of
- * enable operation. When runtime pm is disabled the mode is always on,
- * so sequence doesn't matter.
- */
- ret = bmc150_accel_set_power_state(data, state);
- if (ret < 0)
- return ret;
-
/* map the interrupt to the appropriate pins */
ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
(state ? info->map_bitmask : 0));
@@ -564,10 +535,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
goto out_fix_power_state;
}

+ if (!state)
+ pm_runtime_put_autosuspend(dev);
+
return 0;

out_fix_power_state:
- bmc150_accel_set_power_state(data, false);
+ if (state) {
+ pm_runtime_put_autosuspend(dev);
+ atomic_dec(&intr->users);
+ } else {
+ atomic_inc(&intr->users);
+ }
return ret;
}

@@ -625,8 +604,9 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
__le16 raw_val;

mutex_lock(&data->mutex);
- ret = bmc150_accel_set_power_state(data, true);
+ ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
+ dev_err(dev, "failed to resume: %d\n", ret);
mutex_unlock(&data->mutex);
return ret;
}
@@ -635,16 +615,14 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
&raw_val, sizeof(raw_val));
if (ret < 0) {
dev_err(dev, "Error reading axis %d\n", axis);
- bmc150_accel_set_power_state(data, false);
+ pm_runtime_put_autosuspend(dev);
mutex_unlock(&data->mutex);
return ret;
}
*val = sign_extend32(le16_to_cpu(raw_val) >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
- ret = bmc150_accel_set_power_state(data, false);
+ pm_runtime_put_autosuspend(dev);
mutex_unlock(&data->mutex);
- if (ret < 0)
- return ret;

return IIO_VAL_INT;
}
@@ -1477,8 +1455,14 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
static int bmc150_accel_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ dev_err(dev, "failed to resume: %d\n", ret);

- return bmc150_accel_set_power_state(data, true);
+ return ret;
}

static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev)
@@ -1540,8 +1524,11 @@ static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev)
static int bmc150_accel_buffer_postdisable(struct iio_dev *indio_dev)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);

- return bmc150_accel_set_power_state(data, false);
+ pm_runtime_put_autosuspend(dev);
+
+ return 0;
}

static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
--
2.56.0.218.g1ec904b173-goog