mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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: bc11ca4a0b ("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>
This commit is contained in:
parent
8bf3e7a9de
commit
eaead586b3
|
|
@ -899,6 +899,28 @@ static irqreturn_t ak8975_handle_trigger(int irq, void *p)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ak8975_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ak8975_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = &data->client->dev;
|
||||
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
}
|
||||
|
||||
static int ak8975_buffer_postdisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ak8975_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = &data->client->dev;
|
||||
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops ak8975_buffer_setup_ops = {
|
||||
.preenable = ak8975_buffer_preenable,
|
||||
.postdisable = ak8975_buffer_postdisable,
|
||||
};
|
||||
static int ak8975_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
|
|
@ -992,7 +1014,7 @@ static int ak8975_probe(struct i2c_client *client)
|
|||
indio_dev->name = name;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger,
|
||||
NULL);
|
||||
&ak8975_buffer_setup_ops);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "triggered buffer setup failed\n");
|
||||
goto power_off;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user