Skip to content

Commit fe400da

Browse files
otg-abatecgregkh
authored andcommitted
iio: adc: at91: disable adc channel interrupt in timeout case
commit 09c6bde upstream. 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 <[email protected]> Acked-by: Ludovic Desroches <[email protected]> Cc: <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1ae7297 commit fe400da

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

drivers/iio/adc/at91_adc.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -705,23 +705,29 @@ static int at91_adc_read_raw(struct iio_dev *idev,
705705
ret = wait_event_interruptible_timeout(st->wq_data_avail,
706706
st->done,
707707
msecs_to_jiffies(1000));
708-
if (ret == 0)
709-
ret = -ETIMEDOUT;
710-
if (ret < 0) {
711-
mutex_unlock(&st->lock);
712-
return ret;
713-
}
714-
715-
*val = st->last_value;
716708

709+
/* Disable interrupts, regardless if adc conversion was
710+
* successful or not
711+
*/
717712
at91_adc_writel(st, AT91_ADC_CHDR,
718713
AT91_ADC_CH(chan->channel));
719714
at91_adc_writel(st, AT91_ADC_IDR, BIT(chan->channel));
720715

721-
st->last_value = 0;
722-
st->done = false;
716+
if (ret > 0) {
717+
/* a valid conversion took place */
718+
*val = st->last_value;
719+
st->last_value = 0;
720+
st->done = false;
721+
ret = IIO_VAL_INT;
722+
} else if (ret == 0) {
723+
/* conversion timeout */
724+
dev_err(&idev->dev, "ADC Channel %d timeout.\n",
725+
chan->channel);
726+
ret = -ETIMEDOUT;
727+
}
728+
723729
mutex_unlock(&st->lock);
724-
return IIO_VAL_INT;
730+
return ret;
725731

726732
case IIO_CHAN_INFO_SCALE:
727733
*val = st->vref_mv;

0 commit comments

Comments
 (0)