Skip to content

Commit d5b8103

Browse files
committed
iio: adc: at91-sama5d2_adc: fix channel configuration for differential channels
When iterating through the channels, the index in the array is not the scan index. Added an xlate function to translate to the proper index. The result of the bug is that the channel array is indexed with a wrong index, thus instead of the proper channel, we access invalid memory, which may lead to invalid results and/or corruption. This will be used also for devicetree channel xlate. Fixes: 5e1a1da ("iio: adc: at91-sama5d2_adc: add hw trigger and buffer support") Fixes: 073c662 ("iio: adc: at91-sama5d2_adc: add support for DMA") Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com> Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 9b4e2ec commit d5b8103

1 file changed

Lines changed: 37 additions & 4 deletions

File tree

drivers/iio/adc/at91-sama5d2_adc.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,27 @@ static const struct iio_chan_spec at91_adc_channels[] = {
333333
+ AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
334334
};
335335

336+
static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
337+
{
338+
int i;
339+
340+
for (i = 0; i < indio_dev->num_channels; i++) {
341+
if (indio_dev->channels[i].scan_index == chan)
342+
return i;
343+
}
344+
return -EINVAL;
345+
}
346+
347+
static inline struct iio_chan_spec const *
348+
at91_adc_chan_get(struct iio_dev *indio_dev, int chan)
349+
{
350+
int index = at91_adc_chan_xlate(indio_dev, chan);
351+
352+
if (index < 0)
353+
return NULL;
354+
return indio_dev->channels + index;
355+
}
356+
336357
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
337358
{
338359
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
@@ -350,8 +371,10 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
350371
at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
351372

352373
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
353-
struct iio_chan_spec const *chan = indio->channels + bit;
374+
struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit);
354375

376+
if (!chan)
377+
continue;
355378
if (state) {
356379
at91_adc_writel(st, AT91_SAMA5D2_CHER,
357380
BIT(chan->channel));
@@ -448,7 +471,11 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev)
448471

449472
for_each_set_bit(bit, indio_dev->active_scan_mask,
450473
indio_dev->num_channels) {
451-
struct iio_chan_spec const *chan = indio_dev->channels + bit;
474+
struct iio_chan_spec const *chan =
475+
at91_adc_chan_get(indio_dev, bit);
476+
477+
if (!chan)
478+
continue;
452479

453480
st->dma_st.rx_buf_sz += chan->scan_type.storagebits / 8;
454481
}
@@ -526,8 +553,11 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
526553
*/
527554
for_each_set_bit(bit, indio_dev->active_scan_mask,
528555
indio_dev->num_channels) {
529-
struct iio_chan_spec const *chan = indio_dev->channels + bit;
556+
struct iio_chan_spec const *chan =
557+
at91_adc_chan_get(indio_dev, bit);
530558

559+
if (!chan)
560+
continue;
531561
if (st->dma_st.dma_chan)
532562
at91_adc_readl(st, chan->address);
533563
}
@@ -587,8 +617,11 @@ static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
587617

588618
for_each_set_bit(bit, indio_dev->active_scan_mask,
589619
indio_dev->num_channels) {
590-
struct iio_chan_spec const *chan = indio_dev->channels + bit;
620+
struct iio_chan_spec const *chan =
621+
at91_adc_chan_get(indio_dev, bit);
591622

623+
if (!chan)
624+
continue;
592625
st->buffer[i] = at91_adc_readl(st, chan->address);
593626
i++;
594627
}

0 commit comments

Comments
 (0)