Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: accel: bmc150: Fix irq assumption regression

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>

authored by

Linus Walleij and committed by
Jonathan Cameron
3aa385a9 8abbf45f

+6
+5
drivers/iio/accel/bmc150-accel-core.c
··· 523 523 const struct bmc150_accel_interrupt_info *info = intr->info; 524 524 int ret; 525 525 526 + /* We do not always have an IRQ */ 527 + if (data->irq <= 0) 528 + return 0; 529 + 526 530 if (state) { 527 531 if (atomic_inc_return(&intr->users) > 1) 528 532 return 0; ··· 1700 1696 } 1701 1697 1702 1698 if (irq > 0) { 1699 + data->irq = irq; 1703 1700 ret = devm_request_threaded_irq(dev, irq, 1704 1701 bmc150_accel_irq_handler, 1705 1702 bmc150_accel_irq_thread_handler,
+1
drivers/iio/accel/bmc150-accel.h
··· 58 58 59 59 struct bmc150_accel_data { 60 60 struct regmap *regmap; 61 + int irq; 61 62 struct regulator_bulk_data regulators[2]; 62 63 struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; 63 64 struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];