Commit e19ac9d9 authored by Olivier Moysan's avatar Olivier Moysan Committed by Jonathan Cameron
Browse files

iio: adc: stm32-dfsdm: fix sleep in atomic context



This commit fixes the error message:
"BUG: sleeping function called from invalid context at kernel/irq/chip.c"
Suppress the trigger irq handler. Make the buffer transfers directly
in DMA callback, instead.
Push buffers without timestamps, as timestamps are not supported
in DFSDM driver.

Fixes: 11646e81 ("iio: adc: stm32-dfsdm: add support for buffer modes")

Signed-off-by: default avatarOlivier Moysan <olivier.moysan@st.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent a500f3bd
Loading
Loading
Loading
Loading
+10 −33
Original line number Diff line number Diff line
@@ -842,31 +842,6 @@ static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc,
	}
}

static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
{
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
	int available = stm32_dfsdm_adc_dma_residue(adc);

	while (available >= indio_dev->scan_bytes) {
		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];

		stm32_dfsdm_process_data(adc, buffer);

		iio_push_to_buffers_with_timestamp(indio_dev, buffer,
						   pf->timestamp);
		available -= indio_dev->scan_bytes;
		adc->bufi += indio_dev->scan_bytes;
		if (adc->bufi >= adc->buf_sz)
			adc->bufi = 0;
	}

	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static void stm32_dfsdm_dma_buffer_done(void *data)
{
	struct iio_dev *indio_dev = data;
@@ -874,11 +849,6 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
	int available = stm32_dfsdm_adc_dma_residue(adc);
	size_t old_pos;

	if (indio_dev->currentmode & INDIO_BUFFER_TRIGGERED) {
		iio_trigger_poll_chained(indio_dev->trig);
		return;
	}

	/*
	 * FIXME: In Kernel interface does not support cyclic DMA buffer,and
	 * offers only an interface to push data samples per samples.
@@ -906,7 +876,15 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
			adc->bufi = 0;
			old_pos = 0;
		}
		/* regular iio buffer without trigger */
		/*
		 * In DMA mode the trigger services of IIO are not used
		 * (e.g. no call to iio_trigger_poll).
		 * Calling irq handler associated to the hardware trigger is not
		 * relevant as the conversions have already been done. Data
		 * transfers are performed directly in DMA callback instead.
		 * This implementation avoids to call trigger irq handler that
		 * may sleep, in an atomic context (DMA irq handler context).
		 */
		if (adc->dev_data->type == DFSDM_IIO)
			iio_push_to_buffers(indio_dev, buffer);
	}
@@ -1536,8 +1514,7 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
	}

	ret = iio_triggered_buffer_setup(indio_dev,
					 &iio_pollfunc_store_time,
					 &stm32_dfsdm_adc_trigger_handler,
					 &iio_pollfunc_store_time, NULL,
					 &stm32_dfsdm_buffer_setup_ops);
	if (ret) {
		stm32_dfsdm_dma_release(indio_dev);