[PATCH 12/15] iio: imu: inv_mpu6050: don't disable the IRQ under lock

From: Greg Kroah-Hartman

Date: Tue Oct 27 2026 - 12:47:34 EST


From: Josef Bacik <josef@xxxxxxxxxxxxxx>

If the chip is a wake-up source, inv_mpu_suspend() calls disable_irq() with
st->lock held. disable_irq() waits for the threaded handler, and
inv_mpu6050_interrupt_handle() takes st->lock to read the interrupt
status. If the chip raises an interrupt while the system is being
suspended, the handler waits for the lock, the suspend callback waits for
the handler, and the suspend hangs.

Disable the interrupt once the lock has been dropped.

Fixes: 305914d01807 ("iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode")
Cc: stable <stable@xxxxxxxxxx>
Cc: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@xxxxxxx>
Cc: David Lechner <dlechner@xxxxxxxxxxxx>
Cc: "Nuno Sá" <nuno.sa@xxxxxxxxxx>
Cc: Andy Shevchenko <andy@xxxxxxxxxx>
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 38c3f3b398d4..0ae9d497ccfd 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -2166,7 +2166,7 @@ static int inv_mpu_resume(struct device *dev)
return result;
}

-static int inv_mpu_suspend(struct device *dev)
+static int __inv_mpu_suspend(struct device *dev, bool *disable)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
@@ -2212,7 +2212,7 @@ static int inv_mpu_suspend(struct device *dev)
if (result)
return result;
enable_irq_wake(st->irq);
- disable_irq(st->irq);
+ *disable = true;
} else {
result = inv_mpu6050_set_power_itg(st, false);
if (result)
@@ -2223,6 +2223,21 @@ static int inv_mpu_suspend(struct device *dev)
return 0;
}

+static int inv_mpu_suspend(struct device *dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+ bool disable = false;
+ int result;
+
+ result = __inv_mpu_suspend(dev, &disable);
+
+ /* Not under st->lock: this waits for the handler, which takes it */
+ if (disable)
+ disable_irq(st->irq);
+
+ return result;
+}
+
static int inv_mpu_runtime_suspend(struct device *dev)
{
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));

--
2.56.0