| From 3aa385a9c75c09b59dcab2ff76423439d23673ab Mon Sep 17 00:00:00 2001 |
| From: Linus Walleij <linus.walleij@linaro.org> |
| Date: Mon, 3 Nov 2025 10:36:18 +0100 |
| Subject: iio: accel: bmc150: Fix irq assumption regression |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Linus Walleij <linus.walleij@linaro.org> |
| |
| commit 3aa385a9c75c09b59dcab2ff76423439d23673ab upstream. |
| |
| The code in bmc150-accel-core.c unconditionally calls |
| bmc150_accel_set_interrupt() in the iio_buffer_setup_ops, |
| such as on the runtime PM resume path giving a kernel |
| splat like this if the device has no interrupts: |
| |
| Unable to handle kernel NULL pointer dereference at virtual |
| address 00000001 when read |
| |
| PC is at bmc150_accel_set_interrupt+0x98/0x194 |
| LR is at __pm_runtime_resume+0x5c/0x64 |
| (...) |
| Call trace: |
| bmc150_accel_set_interrupt from bmc150_accel_buffer_postenable+0x40/0x108 |
| bmc150_accel_buffer_postenable from __iio_update_buffers+0xbe0/0xcbc |
| __iio_update_buffers from enable_store+0x84/0xc8 |
| enable_store from kernfs_fop_write_iter+0x154/0x1b4 |
| |
| This bug seems to have been in the driver since the beginning, |
| but it only manifests recently, I do not know why. |
| |
| Store the IRQ number in the state struct, as this is a common |
| pattern in other drivers, then use this to determine if we have |
| IRQ support or not. |
| |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com> |
| Reviewed-by: Nuno Sรก <nuno.sa@analog.com> |
| Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/iio/accel/bmc150-accel-core.c | 5 +++++ |
| drivers/iio/accel/bmc150-accel.h | 1 + |
| 2 files changed, 6 insertions(+) |
| |
| --- a/drivers/iio/accel/bmc150-accel-core.c |
| +++ b/drivers/iio/accel/bmc150-accel-core.c |
| @@ -529,6 +529,10 @@ static int bmc150_accel_set_interrupt(st |
| const struct bmc150_accel_interrupt_info *info = intr->info; |
| int ret; |
| |
| + /* We do not always have an IRQ */ |
| + if (data->irq <= 0) |
| + return 0; |
| + |
| if (state) { |
| if (atomic_inc_return(&intr->users) > 1) |
| return 0; |
| @@ -1702,6 +1706,7 @@ int bmc150_accel_core_probe(struct devic |
| } |
| |
| if (irq > 0) { |
| + data->irq = irq; |
| ret = devm_request_threaded_irq(dev, irq, |
| bmc150_accel_irq_handler, |
| bmc150_accel_irq_thread_handler, |
| --- a/drivers/iio/accel/bmc150-accel.h |
| +++ b/drivers/iio/accel/bmc150-accel.h |
| @@ -57,6 +57,7 @@ enum bmc150_accel_trigger_id { |
| |
| struct bmc150_accel_data { |
| struct regmap *regmap; |
| + int irq; |
| struct regulator_bulk_data regulators[2]; |
| struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; |
| struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; |