patch "iio: imx8qxp-adc: fix irq flood when call imx8qxp_adc_read_raw()" added to char-misc-linus
Subsystems (4)
This is a note to let you know that I've just added the patch titled
iio: imx8qxp-adc: fix irq flood when call imx8qxp_adc_read_raw()
to my char-misc git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
in the char-misc-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 0fc3562a993c3dc41d1177b3983d9300d0db1d4d Mon Sep 17 00:00:00 2001
From: Frank Li <[email protected]>
Date: Thu, 1 Dec 2022 09:01:10 -0500
Subject: iio: imx8qxp-adc: fix irq flood when call imx8qxp_adc_read_raw()
irq flood happen when run
cat /sys/bus/iio/devices/iio:device0/in_voltage1_raw
imx8qxp_adc_read_raw()
{
...
enable irq
/* adc start */
writel(1, adc->regs + IMX8QXP_ADR_ADC_SWTRIG);
^^^^ trigger irq flood.
wait_for_completion_interruptible_timeout();
readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO);
^^^^ clear irq here.
...
}There is only FIFO watermark interrupt at this ADC controller. IRQ line will be assert until software read data from FIFO. So IRQ flood happen during wait_for_completion_interruptible_timeout().
Move FIFO read into irq handle to avoid irq flood.
--- drivers/iio/adc/imx8qxp-adc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/iio/adc/imx8qxp-adc.c +9 -2
@@ -86,6 +86,8 @@#define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100) +#define IMX8QXP_ADC_MAX_FIFO_SIZE 16 +struct imx8qxp_adc {struct device *dev;void __iomem *regs;
@@ -95,6 +97,7 @@ struct imx8qxp_adc {/* Serialise ADC channel reads */ struct mutex lock;struct completion completion; +u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE ]; };#define IMX8QXP_ADC_CHAN (_idx) { \
@@ -238,8 +241,7 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev,return ret; } - *val =FIELD_GET (IMX8QXP_ADC_RESFIFO_VAL_MASK , -readl (adc->regs +IMX8QXP_ADR_ADC_RESFIFO )); + *val = adc->fifo[0 ];mutex_unlock (&adc->lock);return IIO_VAL_INT ;
@@ -265,10 +267,15 @@ static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id) {struct imx8qxp_adc *adc = dev_id;u32 fifo_count; +int i; fifo_count =FIELD_GET (IMX8QXP_ADC_FCTRL_FCOUNT_MASK ,readl (adc->regs +IMX8QXP_ADR_ADC_FCTRL )); +for (i =0 ; i < fifo_count; i++) + adc->fifo[i] =FIELD_GET (IMX8QXP_ADC_RESFIFO_VAL_MASK , +readl_relaxed (adc->regs +IMX8QXP_ADR_ADC_RESFIFO )); +if (fifo_count)complete (&adc->completion);
Signature · 1 line
2.39.1