Re: [PATCH 2/4] iio: pressure: mpl3115: clean up interrupt handling and locking

SeungJu Cheon <[email protected]> Sun, 31 May 2026 19:59:25 +0900
Newsgroups dev.linux.lists.linux-kernel-mentees,org.kernel.vger.linux-iio
Message-ID <CAGwK=3pEPN3EdLGBbXu2kfp-0MAoxm22n5ZOs=XWPX3WLzfSig@mail.gmail.com>
Hi Jonathan,

On Sat, 30 May 2026 12:23 ... Jonathan Cameron wrote:
> > Return IRQ_NONE instead of IRQ_HANDLED when reading
> > INT_SOURCE fails.
>
> As in previous, wrap to 75 chars for commit messges.

Will rewrap to 75 chars.

> > On shared interrupt lines, returning IRQ_HANDLED after a
> > failed register read may prevent other handlers from being
> > invoked.
>
> From what I recall that is simply not true. Given interrupts might
> occur at same moment, the shared interrupt code calls all handlers
> as it can't tell if how many interrupt sources have signalled an
> interrupt.
> Look more closely at what isn't invoked (hint it's about when things
> go wrong!)
> Also, doesn't look to me like this driver supports sharing of the
> interrupt anyway.

You're right, the shared-handler rationale is wrong, and this driver
doesn't share the interrupt anyway. That's a better rationale. I'll
rework the commit message around the spurious-interrupt accounting
aspect rather than shared interrupt handling.

> > Switch the trigger handler from explicit mutex_lock/unlock
> > to scoped_guard() for consistency with the locking style
> > used elsewhere in the driver.
>
> I'm a little dubious about the value of scoped_guard() for such
> simple cases but I guess it is harmless. As Andy called out though,
> different type of change, different patch.
> Hmm. Actually do it by pushing the lock down into the function
> called instead and there you can use a guard(). [...]
> So put it in mpl3115_fill_trig_buffer().

Good idea. I'll move the locking into mpl3115_fill_trig_buffer() with
a guard() so the scope sits next to the accesses it protects, and put
that in its own patch.

> > Move mpl3115_config_interrupt() above the interrupt handler
> > in preparation for the FIFO support added in a subsequent
> > patch.
>
> Separate patch as moving and doing other things just makes for
> harder to review code.

Agreed, I'll split the move into its own patch.

> > No functional change intended.
>
> Except for the one you call out above.

Right. I'll drop that line; the IRQ_NONE change moves to its own
patch and will be described there.

Thanks for the detailed review.

On Sun, May 31, 2026 at 12:23 AM Jonathan Cameron <[email protected]> wrote:
>
> On Sat, 30 May 2026 20:39:36 +0900
> SeungJu Cheon <[email protected]> wrote:
>
> > Return IRQ_NONE instead of IRQ_HANDLED when reading
> > INT_SOURCE fails.
>
> As in previous, wrap to 75 chars for commit messges.
>
> >
> > On shared interrupt lines, returning IRQ_HANDLED after a
> > failed register read may prevent other handlers from being
> > invoked.
>
> From what I recall that is simply not true.  Given interrupts might occur
> at same moment, the shared interrupt code calls all handlers as it can't
> tell if how many interrupt sources have signalled an interrupt.
>
> Look more closely at what isn't invoked (hint it's about when things
> go wrong!)
>
> Also, doesn't look to me like this driver supports sharing of the interrupt
> anyway.
>
>
> >
> > Switch the trigger handler from explicit mutex_lock/unlock
> > to scoped_guard() for consistency with the locking style
> > used elsewhere in the driver.
>
> I'm a little dubious about the value of scoped_guard() for such simple
> cases but I guess it is harmless.  As Andy called out though, different
> type of change, different patch.
>
> Hmm. Actually do it by pushing the lock down into the function called
> instead and there you can use a guard(). Has the added advantage of making
> the exact scope of the locking visible next to the calls in it.
> So put it in mpl3115_fill_trig_buffer().
>
> >
> > Move mpl3115_config_interrupt() above the interrupt handler
> > in preparation for the FIFO support added in a subsequent
> > patch.
>
> Separate patch as moving and doing other things just makes for harder
> to review code.
>
> >
> > No functional change intended.
>
> Except for the one you call out above.
>
> >
> > Signed-off-by: SeungJu Cheon <[email protected]>
> > ---
> >  drivers/iio/pressure/mpl3115.c | 59 +++++++++++++++++-----------------
> >  1 file changed, 29 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
> > index befb6d48efa9..52a3d0d59769 100644
> > --- a/drivers/iio/pressure/mpl3115.c
> > +++ b/drivers/iio/pressure/mpl3115.c
> > @@ -308,9 +308,8 @@ static irqreturn_t mpl3115_trigger_handler(int irq, void *p)
> >       u8 buffer[16] __aligned(8) = { };
> >       int ret;
> >
> > -     mutex_lock(&data->lock);
> > -     ret = mpl3115_fill_trig_buffer(indio_dev, buffer);
> > -     mutex_unlock(&data->lock);
> > +     scoped_guard(mutex, &data->lock)
> > +             ret = mpl3115_fill_trig_buffer(indio_dev, buffer);
> >       if (ret)
> >               goto done;
> >
> > @@ -322,6 +321,32 @@ static irqreturn_t mpl3115_trigger_handler(int irq, void *p)
> >       return IRQ_HANDLED;
> >  }
> >
> > +static int mpl3115_config_interrupt(struct mpl3115_data *data,
> > +                                 u8 ctrl_reg1, u8 ctrl_reg4)
> > +{
> > +     int ret;
> > +
> > +     ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
> > +                                     ctrl_reg1);
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG4,
> > +                                     ctrl_reg4);
> > +     if (ret < 0)
> > +             goto reg1_cleanup;
> > +
> > +     data->ctrl_reg1 = ctrl_reg1;
> > +     data->ctrl_reg4 = ctrl_reg4;
> > +
> > +     return 0;
> > +
> > +reg1_cleanup:
> > +     i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
> > +                               data->ctrl_reg1);
> > +     return ret;
> > +}
> > +
> >  static const struct iio_event_spec mpl3115_temp_press_event[] = {
> >       {
> >               .type = IIO_EV_TYPE_THRESH,
> > @@ -381,7 +406,7 @@ static irqreturn_t mpl3115_interrupt_handler(int irq, void *private)
> >
> >       ret = i2c_smbus_read_byte_data(data->client, MPL3115_INT_SOURCE);
> >       if (ret < 0)
> > -             return IRQ_HANDLED;
> > +             return IRQ_NONE;
>
> So the fun of error handling in interrupt threads.  Arguably we have no idea
> if it was our interrupt or not if this occurs - which I suspect is the motivation
> of the author in returning IRQ_HANDLED here (and IRQ_NONE when we did read but there
> were no interrupts).
>
> I think IRQ_NONE still makes more sense because if we do have an intermittent fault
> and the state is such that the interrupt will retrigger, then it doesn't matter if we
> flag one spurious interrupt.
>
>
> >
> >       if (!(ret & (MPL3115_INT_SRC_TTH | MPL3115_INT_SRC_PTH |
> >                    MPL3115_INT_SRC_DRDY)))
> > @@ -420,32 +445,6 @@ static irqreturn_t mpl3115_interrupt_handler(int irq, void *private)
> >       return IRQ_HANDLED;
> >  }
> >
> > -static int mpl3115_config_interrupt(struct mpl3115_data *data,
> > -                                 u8 ctrl_reg1, u8 ctrl_reg4)
> > -{
> > -     int ret;
> > -
> > -     ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
> > -                                     ctrl_reg1);
> > -     if (ret < 0)
> > -             return ret;
> > -
> > -     ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG4,
> > -                                     ctrl_reg4);
> > -     if (ret < 0)
> > -             goto reg1_cleanup;
> > -
> > -     data->ctrl_reg1 = ctrl_reg1;
> > -     data->ctrl_reg4 = ctrl_reg4;
> > -
> > -     return 0;
> > -
> > -reg1_cleanup:
> > -     i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
> > -                               data->ctrl_reg1);
> > -     return ret;
> > -}
> > -
> >  static int mpl3115_set_trigger_state(struct iio_trigger *trig, bool state)
> >  {
> >       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
>