[PATCH v2 03/17] iio: accel: mma8452: Discard pm_runtime_put_autosuspend() return values

From: Brian Norris

Date: Wed Oct 21 2026 - 20:02:10 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, since the behavior is the same with and without CONFIG_PM.

While I'm at it: I see that mma8452_data_rdy_trigger_set_state() and
mma8452_write_event_config() mismanage the runtime PM reference count,
and instead rely on (racy) autosuspend delay for correct ordering.
Undo this choice, and instead properly drop the reference count only
after we're done touching the hardware.

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:
* Rebase to linux-next properly
* Drop a few drivers' changes, as they stopped checking
pm_runtime_put_autosuspend() return code already
* Split iio patch into per-driver patches
* Inlining
* Autosuspend race fixes

drivers/iio/accel/mma8452.c | 100 ++++++++++++++++++++++--------------
1 file changed, 61 insertions(+), 39 deletions(-)

diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index fe62a903f0e2..7466c40f6239 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -220,26 +220,6 @@ static int mma8452_drdy(struct mma8452_data *data)
return -EIO;
}

-static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on)
-{
-#ifdef CONFIG_PM
- struct device *dev = &client->dev;
- 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 to change power state to %d\n", on);
-
- return ret;
- }
-#endif
-
- return 0;
-}
-
static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
{
int ret = mma8452_drdy(data);
@@ -247,18 +227,20 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
if (ret < 0)
return ret;

- ret = mma8452_set_runtime_pm_state(data->client, true);
- if (ret)
+ ret = pm_runtime_resume_and_get(&data->client->dev);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to resume: %d\n", ret);
return ret;
+ }

ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
3 * sizeof(__be16), (u8 *)buf);
if (ret < 0)
return ret;

- ret = mma8452_set_runtime_pm_state(data->client, false);
+ pm_runtime_put_autosuspend(&data->client->dev);

- return ret;
+ return 0;
}

static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
@@ -974,17 +956,25 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
if (ret)
return ret;

- ret = mma8452_set_runtime_pm_state(data->client, state);
- if (ret)
- return ret;
+ if (state) {
+ ret = pm_runtime_resume_and_get(&data->client->dev);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to resume: %d\n",
+ ret);
+ return ret;
+ }
+ }

switch (dir) {
case IIO_EV_DIR_FALLING:
- return mma8452_set_freefall_mode(data, state);
+ ret = mma8452_set_freefall_mode(data, state);
+ break;
case IIO_EV_DIR_RISING:
val = i2c_smbus_read_byte_data(data->client, ev_regs->ev_cfg);
- if (val < 0)
- return val;
+ if (val < 0) {
+ ret = val;
+ break;
+ }

if (state) {
if (mma8452_freefall_mode_enabled(data)) {
@@ -997,7 +987,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
ev_regs->ev_cfg_chan_shift);
} else {
if (mma8452_freefall_mode_enabled(data))
- return 0;
+ break;

val &= ~BIT(chan->scan_index +
ev_regs->ev_cfg_chan_shift);
@@ -1005,10 +995,23 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,

val |= ev_regs->ev_cfg_ele;

- return mma8452_change_config(data, ev_regs->ev_cfg, val);
+ ret = mma8452_change_config(data, ev_regs->ev_cfg, val);
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret) {
+ if (state)
+ pm_runtime_put_autosuspend(&data->client->dev);
+ return ret;
}
+
+ if (!state)
+ pm_runtime_put_autosuspend(&data->client->dev);
+
+ return 0;
}

static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
@@ -1447,20 +1450,39 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig,
struct mma8452_data *data = iio_priv(indio_dev);
int reg, ret;

- ret = mma8452_set_runtime_pm_state(data->client, state);
- if (ret)
- return ret;
+ if (state) {
+ ret = pm_runtime_resume_and_get(&data->client->dev);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to resume: %d\n",
+ ret);
+ return ret;
+ }
+ }

reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4);
- if (reg < 0)
- return reg;
+ if (reg < 0) {
+ ret = reg;
+ goto err_put_pm;
+ }

if (state)
reg |= MMA8452_INT_DRDY;
else
reg &= ~MMA8452_INT_DRDY;

- return mma8452_change_config(data, MMA8452_CTRL_REG4, reg);
+ ret = mma8452_change_config(data, MMA8452_CTRL_REG4, reg);
+ if (ret)
+ goto err_put_pm;
+
+ if (!state)
+ pm_runtime_put_autosuspend(&data->client->dev);
+
+ return 0;
+
+err_put_pm:
+ if (state)
+ pm_runtime_put_autosuspend(&data->client->dev);
+ return ret;
}

static const struct iio_trigger_ops mma8452_trigger_ops = {
--
2.56.0.218.g1ec904b173-goog