Skip to content

Commit eaead58

Browse files
cjd8jic23
authored andcommitted
iio: magnetometer: ak8975: ensure device is awake for buffered capture
Currently, the ak8975_start_read_axis() can be called while the device is autosuspended, causing two issues: 1. I2C transfers in the aforementioned function will fail or timeout because ak8975_runtime_suspend() disables the device regulators. 2. Since ak8975_fill_buffer() does not hold runtime references, ak8975_runtime_suspend() can run concurrently, and since PM callbacks do not use a locking mechanism, it may cause a race accessing the control register via the I2C bus. Fix this issue by adding struct iio_buffer_setup_ops that contains preenable and postdisable functions to ensure correct that device is powered on when running a buffered capture. Fixes: bc11ca4 ("iio:magnetometer:ak8975: triggered buffer support") Reported-by: Sashiko <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/patchset/20260511-magnetometer-fixes-post-pickup-v7-0-9d910faa28b6%40gmail.com Cc: <Stable@vger.kernel.org> Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
1 parent 8bf3e7a commit eaead58

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

drivers/iio/magnetometer/ak8975.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,28 @@ static irqreturn_t ak8975_handle_trigger(int irq, void *p)
899899
return IRQ_HANDLED;
900900
}
901901

902+
static int ak8975_buffer_preenable(struct iio_dev *indio_dev)
903+
{
904+
struct ak8975_data *data = iio_priv(indio_dev);
905+
struct device *dev = &data->client->dev;
906+
907+
return pm_runtime_resume_and_get(dev);
908+
}
909+
910+
static int ak8975_buffer_postdisable(struct iio_dev *indio_dev)
911+
{
912+
struct ak8975_data *data = iio_priv(indio_dev);
913+
struct device *dev = &data->client->dev;
914+
915+
pm_runtime_put_autosuspend(dev);
916+
917+
return 0;
918+
}
919+
920+
static const struct iio_buffer_setup_ops ak8975_buffer_setup_ops = {
921+
.preenable = ak8975_buffer_preenable,
922+
.postdisable = ak8975_buffer_postdisable,
923+
};
902924
static int ak8975_probe(struct i2c_client *client)
903925
{
904926
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -992,7 +1014,7 @@ static int ak8975_probe(struct i2c_client *client)
9921014
indio_dev->name = name;
9931015

9941016
ret = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger,
995-
NULL);
1017+
&ak8975_buffer_setup_ops);
9961018
if (ret) {
9971019
dev_err(&client->dev, "triggered buffer setup failed\n");
9981020
goto power_off;

0 commit comments

Comments
 (0)