linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] irqchip/stm32-exti: avoid interrupts losing due to clearing pending bit by mistake
@ 2020-08-20  3:16 qiuguorui1
  2020-08-25 23:40 ` [tip: irq/urgent] irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits " tip-bot2 for qiuguorui1
  0 siblings, 1 reply; 2+ messages in thread
From: qiuguorui1 @ 2020-08-20  3:16 UTC (permalink / raw)
  To: tglx, jason, maz, mcoquelin.stm32, alexandre.torgue, ludovic.barre
  Cc: linux-kernel, linux-stm32, linux-arm-kernel, zengweilin,
	chenjianguo3, qiuguorui1

In the previous code, when the eoi handle of the exti clears the pending
bit of the current interrupt, it will first read the values of fpr and
rpr, then logically OR the corresponding bit of the interrupt number,
and finally write back to fpr and rpr.

We found through experiments that if two exti interrupts,
we call them int1/int2, arrive almost at the same time. in our scenario,
the time difference is 30 microseconds, assuming int1 is triggered first.

there will be an extreme scenario: both int's pending bit are set to 1,
the irq handle of int1 is executed first, and eoi handle is then executed,
at this moment, all pending bits are cleared, but the int 2 has not
finally been reported to the cpu yet, which eventually lost int2.

According to stm32's TRM description about rpr and fpr: Writing a 1 to this
bit will trigger a rising edge event on event x, Writing 0 has no
effect.

Therefore, when clearing the pending bit, we only need to clear the
pending bit of the irq.

Changes in v2:
 - simplify the code by calling writel_relaxed directly
   in the function stm32_exti_h_eoi.

v1:https://lore.kernel.org/lkml/20200819023931.28997-1-qiuguorui1@huawei.com/

Signed-off-by: qiuguorui1 <qiuguorui1@huawei.com>
Fixes: 927abfc4461e7 ("irqchip/stm32: Add stm32mp1 support with hierarchy domain")
Cc: stable@vger.kernel.org # v4.18+
---
 drivers/irqchip/irq-stm32-exti.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 03a36be757d8..0c2c61db26b4 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -416,6 +416,16 @@ static void stm32_irq_ack(struct irq_data *d)
 	irq_gc_unlock(gc);
 }
 
+/* directly set the target bit without reading first. */
+static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg)
+{
+	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+	void __iomem *base = chip_data->host_data->base;
+	u32 val = BIT(d->hwirq % IRQS_PER_BANK);
+
+	writel_relaxed(val, base + reg);
+}
+
 static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg)
 {
 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
@@ -449,9 +459,9 @@ static void stm32_exti_h_eoi(struct irq_data *d)
 
 	raw_spin_lock(&chip_data->rlock);
 
-	stm32_exti_set_bit(d, stm32_bank->rpr_ofst);
+	stm32_exti_write_bit(d, stm32_bank->rpr_ofst);
 	if (stm32_bank->fpr_ofst != UNDEF_REG)
-		stm32_exti_set_bit(d, stm32_bank->fpr_ofst);
+		stm32_exti_write_bit(d, stm32_bank->fpr_ofst);
 
 	raw_spin_unlock(&chip_data->rlock);
 
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [tip: irq/urgent] irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by mistake
  2020-08-20  3:16 [PATCH v2] irqchip/stm32-exti: avoid interrupts losing due to clearing pending bit by mistake qiuguorui1
@ 2020-08-25 23:40 ` tip-bot2 for qiuguorui1
  0 siblings, 0 replies; 2+ messages in thread
From: tip-bot2 for qiuguorui1 @ 2020-08-25 23:40 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: qiuguorui1, Marc Zyngier, stable, #, v4.18+, x86, LKML

The following commit has been merged into the irq/urgent branch of tip:

Commit-ID:     e579076ac0a3bebb440fab101aef3c42c9f4c709
Gitweb:        https://git.kernel.org/tip/e579076ac0a3bebb440fab101aef3c42c9f4c709
Author:        qiuguorui1 <qiuguorui1@huawei.com>
AuthorDate:    Thu, 20 Aug 2020 11:16:29 +08:00
Committer:     Marc Zyngier <maz@kernel.org>
CommitterDate: Tue, 25 Aug 2020 10:57:05 +01:00

irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by mistake

In the current code, when the eoi callback of the exti clears the pending
bit of the current interrupt, it will first read the values of fpr and
rpr, then logically OR the corresponding bit of the interrupt number,
and finally write back to fpr and rpr.

We found through experiments that if two exti interrupts,
we call them int1/int2, arrive almost at the same time. in our scenario,
the time difference is 30 microseconds, assuming int1 is triggered first.

there will be an extreme scenario: both int's pending bit are set to 1,
the irq handle of int1 is executed first, and eoi handle is then executed,
at this moment, all pending bits are cleared, but the int 2 has not
finally been reported to the cpu yet, which eventually lost int2.

According to stm32's TRM description about rpr and fpr: Writing a 1 to this
bit will trigger a rising edge event on event x, Writing 0 has no
effect.

Therefore, when clearing the pending bit, we only need to clear the
pending bit of the irq.

Fixes: 927abfc4461e7 ("irqchip/stm32: Add stm32mp1 support with hierarchy domain")
Signed-off-by: qiuguorui1 <qiuguorui1@huawei.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org # v4.18+
Link: https://lore.kernel.org/r/20200820031629.15582-1-qiuguorui1@huawei.com
---
 drivers/irqchip/irq-stm32-exti.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 03a36be..0c2c61d 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -416,6 +416,16 @@ static void stm32_irq_ack(struct irq_data *d)
 	irq_gc_unlock(gc);
 }
 
+/* directly set the target bit without reading first. */
+static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg)
+{
+	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+	void __iomem *base = chip_data->host_data->base;
+	u32 val = BIT(d->hwirq % IRQS_PER_BANK);
+
+	writel_relaxed(val, base + reg);
+}
+
 static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg)
 {
 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
@@ -449,9 +459,9 @@ static void stm32_exti_h_eoi(struct irq_data *d)
 
 	raw_spin_lock(&chip_data->rlock);
 
-	stm32_exti_set_bit(d, stm32_bank->rpr_ofst);
+	stm32_exti_write_bit(d, stm32_bank->rpr_ofst);
 	if (stm32_bank->fpr_ofst != UNDEF_REG)
-		stm32_exti_set_bit(d, stm32_bank->fpr_ofst);
+		stm32_exti_write_bit(d, stm32_bank->fpr_ofst);
 
 	raw_spin_unlock(&chip_data->rlock);
 

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-08-25 23:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-20  3:16 [PATCH v2] irqchip/stm32-exti: avoid interrupts losing due to clearing pending bit by mistake qiuguorui1
2020-08-25 23:40 ` [tip: irq/urgent] irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits " tip-bot2 for qiuguorui1

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).