diff mbox series

[v3,7/9] iio: imu: adis_trigger: Allow level interrupts

Message ID 20240517074750.87376-8-ramona.bolboaca13@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series adis16501 and adis1657x support | expand

Commit Message

Ramona Gradinariu May 17, 2024, 7:47 a.m. UTC
Currently, adis library allows configuration only for edge interrupts,
needed for data ready sampling.
This patch removes the restriction for level interrupts, which are
needed to handle FIFO watermark interrupts.
Furthermore, in case of level interrupts, devm_request_threaded_irq is
used for interrupt allocation, to avoid blocking the processor while
retrieving the FIFO samples.

Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
---
changes in v3:
 - new patch
 drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 18 deletions(-)

--
2.34.1

Comments

Jonathan Cameron May 19, 2024, 6:35 p.m. UTC | #1
On Fri, 17 May 2024 10:47:48 +0300
Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:

> Currently, adis library allows configuration only for edge interrupts,
> needed for data ready sampling.
> This patch removes the restriction for level interrupts, which are
> needed to handle FIFO watermark interrupts.
> Furthermore, in case of level interrupts, devm_request_threaded_irq is
> used for interrupt allocation, to avoid blocking the processor while
> retrieving the FIFO samples.

If respinning for any other reason, I'd rewrap this as a single paragraph.

This looks fine to me, but I'd like an Ack or RB from Nuno.
Last time I poked an adis part predated the common adis library :(

> 
> Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
> ---
> changes in v3:
>  - new patch
>  drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
>  1 file changed, 21 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
> index f890bf842db8..becf1f558b4e 100644
> --- a/drivers/iio/imu/adis_trigger.c
> +++ b/drivers/iio/imu/adis_trigger.c
> @@ -34,21 +34,16 @@ static int adis_validate_irq_flag(struct adis *adis)
>  	if (adis->data->unmasked_drdy)
>  		adis->irq_flag |= IRQF_NO_AUTOEN;
>  	/*
> -	 * Typically this devices have data ready either on the rising edge or
> -	 * on the falling edge of the data ready pin. This checks enforces that
> -	 * one of those is set in the drivers... It defaults to
> -	 * IRQF_TRIGGER_RISING for backward compatibility with devices that
> -	 * don't support changing the pin polarity.
> +	 * Typically adis devices without fifo have data ready either on the

FIFO maybe as it's an acronym.

> +	 * rising edge or on the falling edge of the data ready pin.
> +	 * IMU devices with fifo support have the watermark pin level driven
> +	 * either high or low when the fifo is filled with the desired number
> +	 * of samples.
> +	 * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
> +	 * devices that don't support changing the pin polarity.
>  	 */
> -	if (direction == IRQF_TRIGGER_NONE) {
> +	if (direction == IRQF_TRIGGER_NONE)
>  		adis->irq_flag |= IRQF_TRIGGER_RISING;
> -		return 0;
> -	} else if (direction != IRQF_TRIGGER_RISING &&
> -		   direction != IRQF_TRIGGER_FALLING) {
> -		dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
> -			adis->irq_flag);
> -		return -EINVAL;
> -	}
> 
>  	return 0;
>  }
> @@ -77,11 +72,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
>  	if (ret)
>  		return ret;
> 
> -	ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> -			       &iio_trigger_generic_data_rdy_poll,
> -			       adis->irq_flag,
> -			       indio_dev->name,
> -			       adis->trig);
> +	if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
> +		ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi->irq,
> +						NULL,
> +						&iio_trigger_generic_data_rdy_poll,
> +						adis->irq_flag | IRQF_ONESHOT,
> +						indio_dev->name,
> +						adis->trig);
> +	else
> +		ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> +				       &iio_trigger_generic_data_rdy_poll,
> +				       adis->irq_flag,
> +				       indio_dev->name,
> +				       adis->trig);
>  	if (ret)
>  		return ret;
> 
> --
> 2.34.1
>
Nuno Sá May 21, 2024, 10:56 a.m. UTC | #2
On Fri, 2024-05-17 at 10:47 +0300, Ramona Gradinariu wrote:
> Currently, adis library allows configuration only for edge interrupts,
> needed for data ready sampling.
> This patch removes the restriction for level interrupts, which are
> needed to handle FIFO watermark interrupts.
> Furthermore, in case of level interrupts, devm_request_threaded_irq is
> used for interrupt allocation, to avoid blocking the processor while
> retrieving the FIFO samples.

Technically this not totally accurate (though ends up being true) as we do read
the FIFO samples in a thread already. The part that runs on the top halve should
be:

iio_trigger_generic_data_rdy_poll() -> iio_trigger_poll() -> iio_pollfunc_store_time()

and given the FIFO nature (as the interrupt keeps firing until FIFO_CNT drops
below the watermark), it seems this is enough for you to see some freezes.

Anyhow, I'd say the commit message should be a bit refactored. This also leads to
another minor detail/question (see below)

> 
> Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
> ---
> changes in v3:
>  - new patch
>  drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
>  1 file changed, 21 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
> index f890bf842db8..becf1f558b4e 100644
> --- a/drivers/iio/imu/adis_trigger.c
> +++ b/drivers/iio/imu/adis_trigger.c
> @@ -34,21 +34,16 @@ static int adis_validate_irq_flag(struct adis *adis)
>  	if (adis->data->unmasked_drdy)
>  		adis->irq_flag |= IRQF_NO_AUTOEN;
>  	/*
> -	 * Typically this devices have data ready either on the rising edge
> or
> -	 * on the falling edge of the data ready pin. This checks enforces
> that
> -	 * one of those is set in the drivers... It defaults to
> -	 * IRQF_TRIGGER_RISING for backward compatibility with devices that
> -	 * don't support changing the pin polarity.
> +	 * Typically adis devices without fifo have data ready either on the
> +	 * rising edge or on the falling edge of the data ready pin.
> +	 * IMU devices with fifo support have the watermark pin level driven
> +	 * either high or low when the fifo is filled with the desired number
> +	 * of samples.
> +	 * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
> +	 * devices that don't support changing the pin polarity.
>  	 */
> -	if (direction == IRQF_TRIGGER_NONE) {
> +	if (direction == IRQF_TRIGGER_NONE)
>  		adis->irq_flag |= IRQF_TRIGGER_RISING;
> -		return 0;
> -	} else if (direction != IRQF_TRIGGER_RISING &&
> -		   direction != IRQF_TRIGGER_FALLING) {
> -		dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
> -			adis->irq_flag);
> -		return -EINVAL;
> -	}

I guess then we should rename the function as no actual validation is being
done, right?

> 
>  	return 0;
>  }
> @@ -77,11 +72,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct
> iio_dev *indio_dev)
>  	if (ret)
>  		return ret;
> 
> -	ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> -			       &iio_trigger_generic_data_rdy_poll,
> -			       adis->irq_flag,
> -			       indio_dev->name,
> -			       adis->trig);
> +	if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
> +		ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi-
> >irq,
> +						NULL,
> +						&iio_trigger_generic_data_rdy
> _poll,
> +						adis->irq_flag |
> IRQF_ONESHOT,
> +						indio_dev->name,
> +						adis->trig);

So, this is not really a big deal for me but I wonder if we should actually tie
this change to the device having FIFO support (so a boolean in the adis_data
struct)? It seems to me that's the real reason for the split... With the
boolean, we could also constrain the IRQ level support for devices supporting
FIFOs. Anyhow, since this is the first supported device with a FIFO having the
boolean (while it makes sense to me) may add more overhead than needed to the
series so I'm fine with this as-is.

- Nuno Sá
>
diff mbox series

Patch

diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index f890bf842db8..becf1f558b4e 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -34,21 +34,16 @@  static int adis_validate_irq_flag(struct adis *adis)
 	if (adis->data->unmasked_drdy)
 		adis->irq_flag |= IRQF_NO_AUTOEN;
 	/*
-	 * Typically this devices have data ready either on the rising edge or
-	 * on the falling edge of the data ready pin. This checks enforces that
-	 * one of those is set in the drivers... It defaults to
-	 * IRQF_TRIGGER_RISING for backward compatibility with devices that
-	 * don't support changing the pin polarity.
+	 * Typically adis devices without fifo have data ready either on the
+	 * rising edge or on the falling edge of the data ready pin.
+	 * IMU devices with fifo support have the watermark pin level driven
+	 * either high or low when the fifo is filled with the desired number
+	 * of samples.
+	 * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
+	 * devices that don't support changing the pin polarity.
 	 */
-	if (direction == IRQF_TRIGGER_NONE) {
+	if (direction == IRQF_TRIGGER_NONE)
 		adis->irq_flag |= IRQF_TRIGGER_RISING;
-		return 0;
-	} else if (direction != IRQF_TRIGGER_RISING &&
-		   direction != IRQF_TRIGGER_FALLING) {
-		dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
-			adis->irq_flag);
-		return -EINVAL;
-	}

 	return 0;
 }
@@ -77,11 +72,19 @@  int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
 	if (ret)
 		return ret;

-	ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
-			       &iio_trigger_generic_data_rdy_poll,
-			       adis->irq_flag,
-			       indio_dev->name,
-			       adis->trig);
+	if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
+		ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi->irq,
+						NULL,
+						&iio_trigger_generic_data_rdy_poll,
+						adis->irq_flag | IRQF_ONESHOT,
+						indio_dev->name,
+						adis->trig);
+	else
+		ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
+				       &iio_trigger_generic_data_rdy_poll,
+				       adis->irq_flag,
+				       indio_dev->name,
+				       adis->trig);
 	if (ret)
 		return ret;