[PATCH v4 1/3] iio: imu: inv_mpu6050: fix unbalanced regulator_disable() calls, when probe fails

From: Andrey Skvortsov

Date: Fri Jun 05 2026 - 05:11:56 EST


During a probe function after all regulators are enabled, runtime PM
is enabled. Before probe function finishes, runtime PM triggers and
disables vddio regulator. When probe function fails after vddio
regulator is disabled by runtime PM,
inv_mpu_core_disable_regulator_action() tries to disable already
disabled by runtime PM vddio regulator causing following backtrace:

inv-mpu6050-i2c 1-0068: trigger probe fail -19
WARNING: drivers/regulator/core.c:3244 at _regulator_disable+0x2ac/0x600
Call trace:
_regulator_disable+0x2ac/0x600 (P)
regulator_disable+0xac/0x148
inv_mpu_core_disable_regulator_vddio_action+0x3c/0xb0 [inv_mpu6050]
devm_action_release+0x4c/0x88
release_nodes+0xd8/0x178
devres_release_group+0x214/0x3c8
i2c_device_probe+0x6fc/0x9b0
...
inv-mpu6050-i2c 1-0068: Failed to disable vddio regulator: -5

vddio state is handled in two places: runtime PM and
inv_mpu_core_disable_regulator_vddio_action() devm action.
inv_mpu_core_disable_regulator_vddio_action() has to check, whether
regulator is disabled by runtime PM already. But this information is
available only after runtime PM state is initialized by
pm_runtime_set_active() during a probe. So
inv_mpu_core_disable_regulator_vddio_action() has to be called only
after runtime PM state is initialized. To handle this correctly
runtime PM active status is set just before vddio regulator setup.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@xxxxxxxxx>
Fixes: 07c12b1c007c ("iio: imu: mpu6050: add support for regulator framework")
---

Changes in v4:
- update commit message to address Andy's comment
about functions, callbacks and runtime PM names
- move pm_runtime_set_active just before vddio regulator is enabled
as it was proposed previously in v2.

Changes in v3:
- make patch to be the first patch of the patchset for easier backporting
- update commit message to fix Andy's comment
- don't move pm_runtime_set_active from pm_runtime initialization,
move activation of inv_mpu_core_disable_regulator_action instead

Changes in v2:
- minimize call trace in commit message
- include specific driver name in patch subject
- move pm_runtime_set_active just before vddio regulator is enabled

drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 5796896d54cd8..8c8b4f9a8ff63 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -1862,6 +1862,7 @@ static int inv_mpu_core_disable_regulator_vddio(struct inv_mpu6050_state *st)
static void inv_mpu_core_disable_regulator_action(void *_data)
{
struct inv_mpu6050_state *st = _data;
+ struct device *dev = regmap_get_device(st->map);
int result;

result = regulator_disable(st->vdd_supply);
@@ -1869,7 +1870,8 @@ static void inv_mpu_core_disable_regulator_action(void *_data)
dev_err(regmap_get_device(st->map),
"Failed to disable vdd regulator: %d\n", result);

- inv_mpu_core_disable_regulator_vddio(st);
+ if (!pm_runtime_status_suspended(dev))
+ inv_mpu_core_disable_regulator_vddio(st);
}

static void inv_mpu_pm_disable(void *data)
@@ -1970,6 +1972,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}
msleep(INV_MPU6050_POWER_UP_TIME);

+ /* set pm_runtime active early for disable vddio resource cleanup */
+ result = pm_runtime_set_active(dev);
+ if (result)
+ return result;
+
result = inv_mpu_core_enable_regulator_vddio(st);
if (result) {
regulator_disable(st->vdd_supply);
@@ -2015,9 +2022,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}

/* chip init is done, turning on runtime power management */
- result = pm_runtime_set_active(dev);
- if (result)
- goto error_power_off;
pm_runtime_get_noresume(dev);
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, INV_MPU6050_SUSPEND_DELAY_MS);
--
2.53.0