+++ /dev/null
-From dcb10920179ab74caf88a6f2afadecfc2743b910 Mon Sep 17 00:00:00 2001
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-Date: Tue, 17 Sep 2019 14:38:16 +0200
-Subject: iio: adc: stm32-adc: fix a race when using several adcs with dma and irq
-
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-
-commit dcb10920179ab74caf88a6f2afadecfc2743b910 upstream.
-
-End of conversion may be handled by using IRQ or DMA. There may be a
-race when two conversions complete at the same time on several ADCs.
-EOC can be read as 'set' for several ADCs, with:
-- an ADC configured to use IRQs. EOCIE bit is set. The handler is normally
- called in this case.
-- an ADC configured to use DMA. EOCIE bit isn't set. EOC triggers the DMA
- request instead. It's then automatically cleared by DMA read. But the
- handler gets called due to status bit is temporarily set (IRQ triggered
- by the other ADC).
-So both EOC status bit in CSR and EOCIE control bit must be checked
-before invoking the interrupt handler (e.g. call ISR only for
-IRQ-enabled ADCs).
-
-Fixes: 2763ea0585c9 ("iio: adc: stm32: add optional dma support")
-
-Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
-Cc: <Stable@vger.kernel.org>
-Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/iio/adc/stm32-adc-core.c | 43 ++++++++++++++++++++++++++++++++++++---
- drivers/iio/adc/stm32-adc-core.h | 1
- 2 files changed, 41 insertions(+), 3 deletions(-)
-
---- a/drivers/iio/adc/stm32-adc-core.c
-+++ b/drivers/iio/adc/stm32-adc-core.c
-@@ -72,12 +72,16 @@
- * @eoc1: adc1 end of conversion flag in @csr
- * @eoc2: adc2 end of conversion flag in @csr
- * @eoc3: adc3 end of conversion flag in @csr
-+ * @ier: interrupt enable register offset for each adc
-+ * @eocie_msk: end of conversion interrupt enable mask in @ier
- */
- struct stm32_adc_common_regs {
- u32 csr;
- u32 eoc1_msk;
- u32 eoc2_msk;
- u32 eoc3_msk;
-+ u32 ier;
-+ u32 eocie_msk;
- };
-
- struct stm32_adc_priv;
-@@ -271,6 +275,8 @@ static const struct stm32_adc_common_reg
- .eoc1_msk = STM32F4_EOC1,
- .eoc2_msk = STM32F4_EOC2,
- .eoc3_msk = STM32F4_EOC3,
-+ .ier = STM32F4_ADC_CR1,
-+ .eocie_msk = STM32F4_EOCIE,
- };
-
- /* STM32H7 common registers definitions */
-@@ -278,8 +284,24 @@ static const struct stm32_adc_common_reg
- .csr = STM32H7_ADC_CSR,
- .eoc1_msk = STM32H7_EOC_MST,
- .eoc2_msk = STM32H7_EOC_SLV,
-+ .ier = STM32H7_ADC_IER,
-+ .eocie_msk = STM32H7_EOCIE,
- };
-
-+static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
-+ 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
-+};
-+
-+static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
-+ unsigned int adc)
-+{
-+ u32 ier, offset = stm32_adc_offset[adc];
-+
-+ ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier);
-+
-+ return ier & priv->cfg->regs->eocie_msk;
-+}
-+
- /* ADC common interrupt for all instances */
- static void stm32_adc_irq_handler(struct irq_desc *desc)
- {
-@@ -290,13 +312,28 @@ static void stm32_adc_irq_handler(struct
- chained_irq_enter(chip, desc);
- status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
-
-- if (status & priv->cfg->regs->eoc1_msk)
-+ /*
-+ * End of conversion may be handled by using IRQ or DMA. There may be a
-+ * race here when two conversions complete at the same time on several
-+ * ADCs. EOC may be read 'set' for several ADCs, with:
-+ * - an ADC configured to use DMA (EOC triggers the DMA request, and
-+ * is then automatically cleared by DR read in hardware)
-+ * - an ADC configured to use IRQs (EOCIE bit is set. The handler must
-+ * be called in this case)
-+ * So both EOC status bit in CSR and EOCIE control bit must be checked
-+ * before invoking the interrupt handler (e.g. call ISR only for
-+ * IRQ-enabled ADCs).
-+ */
-+ if (status & priv->cfg->regs->eoc1_msk &&
-+ stm32_adc_eoc_enabled(priv, 0))
- generic_handle_irq(irq_find_mapping(priv->domain, 0));
-
-- if (status & priv->cfg->regs->eoc2_msk)
-+ if (status & priv->cfg->regs->eoc2_msk &&
-+ stm32_adc_eoc_enabled(priv, 1))
- generic_handle_irq(irq_find_mapping(priv->domain, 1));
-
-- if (status & priv->cfg->regs->eoc3_msk)
-+ if (status & priv->cfg->regs->eoc3_msk &&
-+ stm32_adc_eoc_enabled(priv, 2))
- generic_handle_irq(irq_find_mapping(priv->domain, 2));
-
- chained_irq_exit(chip, desc);
---- a/drivers/iio/adc/stm32-adc-core.h
-+++ b/drivers/iio/adc/stm32-adc-core.h
-@@ -37,6 +37,7 @@
- * --------------------------------------------------------
- */
- #define STM32_ADC_MAX_ADCS 3
-+#define STM32_ADC_OFFSET 0x100
- #define STM32_ADCX_COMN_OFFSET 0x300
-
- /**
staging-vt6655-fix-memory-leak-in-vt6655_probe.patch
iio-adc-ad799x-fix-probe-error-handling.patch
iio-adc-axp288-override-ts-pin-bias-current-for-some-models.patch
-iio-adc-stm32-adc-fix-a-race-when-using-several-adcs-with-dma-and-irq.patch
+++ /dev/null
-From dcb10920179ab74caf88a6f2afadecfc2743b910 Mon Sep 17 00:00:00 2001
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-Date: Tue, 17 Sep 2019 14:38:16 +0200
-Subject: iio: adc: stm32-adc: fix a race when using several adcs with dma and irq
-
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-
-commit dcb10920179ab74caf88a6f2afadecfc2743b910 upstream.
-
-End of conversion may be handled by using IRQ or DMA. There may be a
-race when two conversions complete at the same time on several ADCs.
-EOC can be read as 'set' for several ADCs, with:
-- an ADC configured to use IRQs. EOCIE bit is set. The handler is normally
- called in this case.
-- an ADC configured to use DMA. EOCIE bit isn't set. EOC triggers the DMA
- request instead. It's then automatically cleared by DMA read. But the
- handler gets called due to status bit is temporarily set (IRQ triggered
- by the other ADC).
-So both EOC status bit in CSR and EOCIE control bit must be checked
-before invoking the interrupt handler (e.g. call ISR only for
-IRQ-enabled ADCs).
-
-Fixes: 2763ea0585c9 ("iio: adc: stm32: add optional dma support")
-
-Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
-Cc: <Stable@vger.kernel.org>
-Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/iio/adc/stm32-adc-core.c | 43 ++++++++++++++++++++++++++++++++++++---
- drivers/iio/adc/stm32-adc-core.h | 1
- 2 files changed, 41 insertions(+), 3 deletions(-)
-
---- a/drivers/iio/adc/stm32-adc-core.c
-+++ b/drivers/iio/adc/stm32-adc-core.c
-@@ -54,12 +54,16 @@
- * @eoc1: adc1 end of conversion flag in @csr
- * @eoc2: adc2 end of conversion flag in @csr
- * @eoc3: adc3 end of conversion flag in @csr
-+ * @ier: interrupt enable register offset for each adc
-+ * @eocie_msk: end of conversion interrupt enable mask in @ier
- */
- struct stm32_adc_common_regs {
- u32 csr;
- u32 eoc1_msk;
- u32 eoc2_msk;
- u32 eoc3_msk;
-+ u32 ier;
-+ u32 eocie_msk;
- };
-
- struct stm32_adc_priv;
-@@ -268,6 +272,8 @@ static const struct stm32_adc_common_reg
- .eoc1_msk = STM32F4_EOC1,
- .eoc2_msk = STM32F4_EOC2,
- .eoc3_msk = STM32F4_EOC3,
-+ .ier = STM32F4_ADC_CR1,
-+ .eocie_msk = STM32F4_EOCIE,
- };
-
- /* STM32H7 common registers definitions */
-@@ -275,8 +281,24 @@ static const struct stm32_adc_common_reg
- .csr = STM32H7_ADC_CSR,
- .eoc1_msk = STM32H7_EOC_MST,
- .eoc2_msk = STM32H7_EOC_SLV,
-+ .ier = STM32H7_ADC_IER,
-+ .eocie_msk = STM32H7_EOCIE,
- };
-
-+static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
-+ 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
-+};
-+
-+static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
-+ unsigned int adc)
-+{
-+ u32 ier, offset = stm32_adc_offset[adc];
-+
-+ ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier);
-+
-+ return ier & priv->cfg->regs->eocie_msk;
-+}
-+
- /* ADC common interrupt for all instances */
- static void stm32_adc_irq_handler(struct irq_desc *desc)
- {
-@@ -287,13 +309,28 @@ static void stm32_adc_irq_handler(struct
- chained_irq_enter(chip, desc);
- status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
-
-- if (status & priv->cfg->regs->eoc1_msk)
-+ /*
-+ * End of conversion may be handled by using IRQ or DMA. There may be a
-+ * race here when two conversions complete at the same time on several
-+ * ADCs. EOC may be read 'set' for several ADCs, with:
-+ * - an ADC configured to use DMA (EOC triggers the DMA request, and
-+ * is then automatically cleared by DR read in hardware)
-+ * - an ADC configured to use IRQs (EOCIE bit is set. The handler must
-+ * be called in this case)
-+ * So both EOC status bit in CSR and EOCIE control bit must be checked
-+ * before invoking the interrupt handler (e.g. call ISR only for
-+ * IRQ-enabled ADCs).
-+ */
-+ if (status & priv->cfg->regs->eoc1_msk &&
-+ stm32_adc_eoc_enabled(priv, 0))
- generic_handle_irq(irq_find_mapping(priv->domain, 0));
-
-- if (status & priv->cfg->regs->eoc2_msk)
-+ if (status & priv->cfg->regs->eoc2_msk &&
-+ stm32_adc_eoc_enabled(priv, 1))
- generic_handle_irq(irq_find_mapping(priv->domain, 1));
-
-- if (status & priv->cfg->regs->eoc3_msk)
-+ if (status & priv->cfg->regs->eoc3_msk &&
-+ stm32_adc_eoc_enabled(priv, 2))
- generic_handle_irq(irq_find_mapping(priv->domain, 2));
-
- chained_irq_exit(chip, desc);
---- a/drivers/iio/adc/stm32-adc-core.h
-+++ b/drivers/iio/adc/stm32-adc-core.h
-@@ -25,6 +25,7 @@
- * --------------------------------------------------------
- */
- #define STM32_ADC_MAX_ADCS 3
-+#define STM32_ADC_OFFSET 0x100
- #define STM32_ADCX_COMN_OFFSET 0x300
-
- /**
iio-adc-hx711-fix-bug-in-sampling-of-data.patch
iio-adc-ad799x-fix-probe-error-handling.patch
iio-adc-axp288-override-ts-pin-bias-current-for-some-models.patch
-iio-adc-stm32-adc-fix-a-race-when-using-several-adcs-with-dma-and-irq.patch