On Wed, Jan 30, 2019 at 02:42:02PM +0100, g.ottinger@xxxxxxxxx wrote: > From: Georg Ottinger <g.ottinger@xxxxxxxxx> > > Having a brief look at at91_adc_read_raw() it is obvious that in the case > of a timeout the setting of AT91_ADC_CHDR and AT91_ADC_IDR registers is > omitted. If 2 different channels are queried we can end up with a > situation where two interrupts are enabled, but only one interrupt is > cleared in the interrupt handler. Resulting in a interrupt loop and a > system hang. > > Signed-off-by: Georg Ottinger <g.ottinger@xxxxxxxxx> Acked-by: Ludovic Desroches <ludovic.desroches@xxxxxxxxxxxxx> Thanks > --- > drivers/iio/adc/at91_adc.c | 28 +++++++++++++++++----------- > 1 file changed, 17 insertions(+), 11 deletions(-) > > diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c > index 75d2f7358..596841a3c 100644 > --- a/drivers/iio/adc/at91_adc.c > +++ b/drivers/iio/adc/at91_adc.c > @@ -704,23 +704,29 @@ static int at91_adc_read_raw(struct iio_dev *idev, > ret = wait_event_interruptible_timeout(st->wq_data_avail, > st->done, > msecs_to_jiffies(1000)); > - if (ret == 0) > - ret = -ETIMEDOUT; > - if (ret < 0) { > - mutex_unlock(&st->lock); > - return ret; > - } > - > - *val = st->last_value; > > + /* Disable interrupts, regardless if adc conversion was > + * successful or not > + */ > at91_adc_writel(st, AT91_ADC_CHDR, > AT91_ADC_CH(chan->channel)); > at91_adc_writel(st, AT91_ADC_IDR, BIT(chan->channel)); > > - st->last_value = 0; > - st->done = false; > + if (ret > 0) { > + /* a valid conversion took place */ > + *val = st->last_value; > + st->last_value = 0; > + st->done = false; > + ret = IIO_VAL_INT; > + } else if (ret == 0) { > + /* conversion timeout */ > + dev_err(&idev->dev, "ADC Channel %d timeout.\n", > + chan->channel); > + ret = -ETIMEDOUT; > + } > + > mutex_unlock(&st->lock); > - return IIO_VAL_INT; > + return ret; > > case IIO_CHAN_INFO_SCALE: > *val = st->vref_mv; > -- > 2.17.1 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel