diff mbox series

[13/16] iio: adc: max1027: Prepare re-using the EOC interrupt

Message ID 20210818111139.330636-14-miquel.raynal@bootlin.com (mailing list archive)
State Changes Requested
Headers show
Series Bring software triggers support to MAX1027-like ADCs | expand

Commit Message

Miquel Raynal Aug. 18, 2021, 11:11 a.m. UTC
Right now the driver only has hardware trigger support, which makes use
of the End Of Conversion (EOC) interrupt by:
- Enabling the external trigger
- At completion of the conversion, run a generic handler
- Push the data to the IIO subsystem by using the triggered buffer
  infrastructure, which may not only serve this purpose.

In fact, the interrupt will fire for more reasons than just a hardware
trigger condition, so make a dedicated interrupt handler which will be
enhanced by the upcoming changes to handle more situations.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/iio/adc/max1027.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

Comments

Nuno Sá Aug. 20, 2021, 7:31 a.m. UTC | #1
> -----Original Message-----
> From: Miquel Raynal <miquel.raynal@bootlin.com>
> Sent: Wednesday, August 18, 2021 1:12 PM
> To: Jonathan Cameron <jic23@kernel.org>; Lars-Peter Clausen
> <lars@metafoo.de>
> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>; linux-
> iio@vger.kernel.org; linux-kernel@vger.kernel.org; Miquel Raynal
> <miquel.raynal@bootlin.com>
> Subject: [PATCH 13/16] iio: adc: max1027: Prepare re-using the EOC
> interrupt
> 
> [External]
> 
> Right now the driver only has hardware trigger support, which makes
> use
> of the End Of Conversion (EOC) interrupt by:
> - Enabling the external trigger
> - At completion of the conversion, run a generic handler
> - Push the data to the IIO subsystem by using the triggered buffer
>   infrastructure, which may not only serve this purpose.
> 
> In fact, the interrupt will fire for more reasons than just a hardware
> trigger condition, so make a dedicated interrupt handler which will be
> enhanced by the upcoming changes to handle more situations.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/iio/adc/max1027.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
> index 2d6485591761..8d86e77fb5db 100644
> --- a/drivers/iio/adc/max1027.c
> +++ b/drivers/iio/adc/max1027.c
> @@ -472,6 +472,24 @@ static int max1027_read_scan(struct iio_dev
> *indio_dev)
>  	return 0;
>  }
> 
> +static irqreturn_t max1027_eoc_irq_handler(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct max1027_state *st = iio_priv(indio_dev);
> +	int ret = 0;
> +
> +	if (st->cnvst_trigger) {
> +		ret = max1027_read_scan(indio_dev);
> +		iio_trigger_notify_done(indio_dev->trig);
> +	}
> +
> +	if (ret)
> +		dev_err(&indio_dev->dev,
> +			"Cannot read scanned values (%d)\n", ret);

Huh? Shouldn't this be right after 'max1027_read_scan()'?

- Nuno Sá

> +	return IRQ_HANDLED;
> +}
> +
>  static irqreturn_t max1027_trigger_handler(int irq, void *private)
>  {
>  	struct iio_poll_func *pf = private;
> @@ -563,11 +581,11 @@ static int max1027_probe(struct spi_device
> *spi)
>  		}
> 
>  		ret = devm_request_threaded_irq(&spi->dev, spi->irq,
> -
> 	iio_trigger_generic_data_rdy_poll,
> +
> 	max1027_eoc_irq_handler,
>  						NULL,
> 
> 	IRQF_TRIGGER_FALLING,
>  						spi->dev.driver->name,
> -						st->trig);
> +						indio_dev);
>  		if (ret < 0) {
>  			dev_err(&indio_dev->dev, "Failed to allocate
> IRQ.\n");
>  			return ret;
> --
> 2.27.0
Jonathan Cameron Aug. 30, 2021, 10:30 a.m. UTC | #2
On Wed, 18 Aug 2021 13:11:36 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Right now the driver only has hardware trigger support, which makes use
> of the End Of Conversion (EOC) interrupt by:
> - Enabling the external trigger
> - At completion of the conversion, run a generic handler
> - Push the data to the IIO subsystem by using the triggered buffer
>   infrastructure, which may not only serve this purpose.
> 
> In fact, the interrupt will fire for more reasons than just a hardware
> trigger condition, so make a dedicated interrupt handler which will be
> enhanced by the upcoming changes to handle more situations.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
one suggestion inline.
> ---
>  drivers/iio/adc/max1027.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
> index 2d6485591761..8d86e77fb5db 100644
> --- a/drivers/iio/adc/max1027.c
> +++ b/drivers/iio/adc/max1027.c
> @@ -472,6 +472,24 @@ static int max1027_read_scan(struct iio_dev *indio_dev)
>  	return 0;
>  }
>  
> +static irqreturn_t max1027_eoc_irq_handler(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct max1027_state *st = iio_priv(indio_dev);
> +	int ret = 0;
> +
> +	if (st->cnvst_trigger) {

I missed this earlier, but it is very similar in purpose to the
logic used in iio_trigger_validate_own_device.  Perhaps you could reuse that
rather than carrying an explicit variable to check for this?

> +		ret = max1027_read_scan(indio_dev);
> +		iio_trigger_notify_done(indio_dev->trig);
> +	}
> +
> +	if (ret)
> +		dev_err(&indio_dev->dev,
> +			"Cannot read scanned values (%d)\n", ret);

Perhaps better to move that into the if statement.  I guess this may
make more sense later though!


> +
> +	return IRQ_HANDLED;
> +}
> +
>  static irqreturn_t max1027_trigger_handler(int irq, void *private)
>  {
>  	struct iio_poll_func *pf = private;
> @@ -563,11 +581,11 @@ static int max1027_probe(struct spi_device *spi)
>  		}
>  
>  		ret = devm_request_threaded_irq(&spi->dev, spi->irq,
> -						iio_trigger_generic_data_rdy_poll,
> +						max1027_eoc_irq_handler,
>  						NULL,
>  						IRQF_TRIGGER_FALLING,
>  						spi->dev.driver->name,
> -						st->trig);
> +						indio_dev);
>  		if (ret < 0) {
>  			dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
>  			return ret;
Jonathan Cameron Aug. 30, 2021, 10:47 a.m. UTC | #3
On Wed, 18 Aug 2021 13:11:36 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Right now the driver only has hardware trigger support, which makes use
> of the End Of Conversion (EOC) interrupt by:
> - Enabling the external trigger
> - At completion of the conversion, run a generic handler
> - Push the data to the IIO subsystem by using the triggered buffer
>   infrastructure, which may not only serve this purpose.
> 
> In fact, the interrupt will fire for more reasons than just a hardware
> trigger condition, so make a dedicated interrupt handler which will be
> enhanced by the upcoming changes to handle more situations.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/iio/adc/max1027.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
> index 2d6485591761..8d86e77fb5db 100644
> --- a/drivers/iio/adc/max1027.c
> +++ b/drivers/iio/adc/max1027.c
> @@ -472,6 +472,24 @@ static int max1027_read_scan(struct iio_dev *indio_dev)
>  	return 0;
>  }
>  
> +static irqreturn_t max1027_eoc_irq_handler(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct max1027_state *st = iio_priv(indio_dev);
> +	int ret = 0;
> +
> +	if (st->cnvst_trigger) {
> +		ret = max1027_read_scan(indio_dev);
> +		iio_trigger_notify_done(indio_dev->trig);

Hmm. Having read on I now realise how you have decided to handle this.
For the 'data ready' type interrupts you are bypassing the triggering
framework entirely. in which case iio_trigger_notify_done() is irrelevant
as the iio_trigger_poll() has never been called.

Normally we only do this sort of bypassing of the trigger infrastructure
when there is a hw fifo involved and hence a given 'interrupt' doesn't
represent a single trigger.  Where possible we do expose the trigger
because it can in turn be used to trigger other devices. 
In this driver that is currently prevented by the validate_device() callback
for the trigger so arguably the change you make here has no affect.

I wonder how hard it would be to change things to allow the validate_device()
protection to be dropped.  There is a slightly nasty corner case where another
device is attached to this trigger but this device is not.  We don't need to
make that 'work' as such because it makes little sense, but we do need to ensure
that things don't blow up if someone configure it like that.

> +	}
> +
> +	if (ret)
> +		dev_err(&indio_dev->dev,
> +			"Cannot read scanned values (%d)\n", ret);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  static irqreturn_t max1027_trigger_handler(int irq, void *private)
>  {
>  	struct iio_poll_func *pf = private;
> @@ -563,11 +581,11 @@ static int max1027_probe(struct spi_device *spi)
>  		}
>  
>  		ret = devm_request_threaded_irq(&spi->dev, spi->irq,
> -						iio_trigger_generic_data_rdy_poll,
> +						max1027_eoc_irq_handler,
>  						NULL,
>  						IRQF_TRIGGER_FALLING,
>  						spi->dev.driver->name,
> -						st->trig);
> +						indio_dev);
>  		if (ret < 0) {
>  			dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
>  			return ret;
diff mbox series

Patch

diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 2d6485591761..8d86e77fb5db 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -472,6 +472,24 @@  static int max1027_read_scan(struct iio_dev *indio_dev)
 	return 0;
 }
 
+static irqreturn_t max1027_eoc_irq_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct max1027_state *st = iio_priv(indio_dev);
+	int ret = 0;
+
+	if (st->cnvst_trigger) {
+		ret = max1027_read_scan(indio_dev);
+		iio_trigger_notify_done(indio_dev->trig);
+	}
+
+	if (ret)
+		dev_err(&indio_dev->dev,
+			"Cannot read scanned values (%d)\n", ret);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t max1027_trigger_handler(int irq, void *private)
 {
 	struct iio_poll_func *pf = private;
@@ -563,11 +581,11 @@  static int max1027_probe(struct spi_device *spi)
 		}
 
 		ret = devm_request_threaded_irq(&spi->dev, spi->irq,
-						iio_trigger_generic_data_rdy_poll,
+						max1027_eoc_irq_handler,
 						NULL,
 						IRQF_TRIGGER_FALLING,
 						spi->dev.driver->name,
-						st->trig);
+						indio_dev);
 		if (ret < 0) {
 			dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
 			return ret;