public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] irqchip/renesas-rzg2l: Bug fixes and NMI support
@ 2026-03-28 10:33 Biju
  2026-03-28 10:33 ` [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free Biju
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Biju @ 2026-03-28 10:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Biju Das, linux-kernel, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	Biju Das, linux-renesas-soc

From: Biju Das <biju.das.jz@bp.renesas.com>

This series contains two bug fixes and a new feature for the Renesas
RZ/G2L IRQC driver.

Patch 1 fixes a bug where the shared IRQ bit is not cleared on free.
When irq_domain_free_irqs_common() is called, it internally resets
irq_data->hwirq to 0 via irq_domain_reset_irq_data(). The fix caches hwirq
before calling irq_domain_free_irqs_common().

Patch 2 simplifies the locking logic in rzg2l_irq_set_type() by replacing
the open-coded raw_spin_{lock,unlock} pair with guard(), and adds the
missing cleanup.h header.

Patch 3 adds NMI support, introducing a dedicated IRQ chip with EOI
handling, trigger type configuration, and suspend/resume support.

NMI Testing on RZ/G3L SMARC EVK:
:~# cat /proc/interrupts | grep NMI
 59:          0          0          0          0 rzg2l-irqc   0 Edge      NMI

Pull down GP_INT# line on green pack device by I2C command
:~# i2cset -y  -f 0 0x38 0x30 0x00; sleep 1; i2cset -y  -f 0 0x38 0x30 0x18

:~# cat /proc/interrupts | grep NMI
 59:          1          0          0          0 rzg2l-irqc   0 Edge      NMI
root@smarc-rzg3l:~#

Biju Das (3):
  irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free
  irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in
    rzg2l_irq_set_type()
  irqchip/renesas-rzg2l: Add NMI support

 drivers/irqchip/irq-renesas-rzg2l.c | 105 +++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 8 deletions(-)

-- 
2.43.0


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

* [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free
  2026-03-28 10:33 [PATCH 0/3] irqchip/renesas-rzg2l: Bug fixes and NMI support Biju
@ 2026-03-28 10:33 ` Biju
  2026-03-31 17:26   ` [tip: irq/drivers] irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free() tip-bot2 for Biju Das
  2026-03-28 10:33 ` [PATCH 2/3] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type() Biju
  2026-03-28 10:33 ` [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support Biju
  2 siblings, 1 reply; 13+ messages in thread
From: Biju @ 2026-03-28 10:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Biju Das, linux-kernel, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	Biju Das, linux-renesas-soc

From: Biju Das <biju.das.jz@bp.renesas.com>

Calling irq_domain_free_irqs_common() internally calls
irq_domain_reset_irq_data(), which explicitly sets irq_data->hwirq
to 0. Consequently, irqd_to_hwirq(d) returns 0 when called after it.
Since 0 falls outside the valid shared IRQ ranges,
rzg2l_irqc_is_shared_and_get_irq_num() evaluates to false, completely
bypassing the test_and_clear_bit() operation. This leaves the bit set
in priv->used_irqs, causing future allocations to fail with -EBUSY.
Fix this by retrieving irq_data and caching hwirq before calling
irq_domain_free_irqs_common().

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
 drivers/irqchip/irq-renesas-rzg2l.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index f5c4d7e0aec3..3cc1efd8d914 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -699,15 +699,14 @@ static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq,
 
 static void rzg2l_irqc_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)
 {
+	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 	struct rzg2l_irqc_priv *priv = domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	irq_domain_free_irqs_common(domain, virq, nr_irqs);
 
-	if (priv->info.shared_irq_cnt) {
-		struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-
-		rzg2l_irqc_shared_irq_free(priv, irqd_to_hwirq(d));
-	}
+	if (priv->info.shared_irq_cnt)
+		rzg2l_irqc_shared_irq_free(priv, hwirq);
 }
 
 static const struct irq_domain_ops rzg2l_irqc_domain_ops = {
-- 
2.43.0


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

* [PATCH 2/3] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type()
  2026-03-28 10:33 [PATCH 0/3] irqchip/renesas-rzg2l: Bug fixes and NMI support Biju
  2026-03-28 10:33 ` [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free Biju
@ 2026-03-28 10:33 ` Biju
  2026-03-28 13:20   ` [tip: irq/drivers] " tip-bot2 for Biju Das
  2026-03-28 10:33 ` [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support Biju
  2 siblings, 1 reply; 13+ messages in thread
From: Biju @ 2026-03-28 10:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Biju Das, linux-kernel, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	Biju Das, linux-renesas-soc

From: Biju Das <biju.das.jz@bp.renesas.com>

Simplify the locking logic in rzg2l_irq_set_type() by using guard(),
eliminating the need for an explicit unlock call.

While at it, add the missing cleanup.h header file.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
 drivers/irqchip/irq-renesas-rzg2l.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 3cc1efd8d914..0f1157d5ce55 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -373,14 +374,13 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	raw_spin_lock(&priv->lock);
+	guard(raw_spinlock)(&priv->lock);
 	tmp = readl_relaxed(priv->base + IITSR);
 	tmp &= ~IITSR_IITSEL_MASK(iitseln);
 	tmp |= IITSR_IITSEL(iitseln, sense);
 	if (clear_irq_int)
 		rzg2l_clear_irq_int(priv, hwirq);
 	writel_relaxed(tmp, priv->base + IITSR);
-	raw_spin_unlock(&priv->lock);
 
 	return 0;
 }
-- 
2.43.0


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

* [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-28 10:33 [PATCH 0/3] irqchip/renesas-rzg2l: Bug fixes and NMI support Biju
  2026-03-28 10:33 ` [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free Biju
  2026-03-28 10:33 ` [PATCH 2/3] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type() Biju
@ 2026-03-28 10:33 ` Biju
  2026-03-28 16:19   ` Wolfram Sang
  2026-03-31 16:15   ` Thomas Gleixner
  2 siblings, 2 replies; 13+ messages in thread
From: Biju @ 2026-03-28 10:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Biju Das, linux-kernel, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	Biju Das, linux-renesas-soc

From: Biju Das <biju.das.jz@bp.renesas.com>

The RZ/G3L SoC has an NMI interrupt. Add support for the NMI interrupt.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
 drivers/irqchip/irq-renesas-rzg2l.c | 92 ++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 0f1157d5ce55..622a9045b606 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -21,11 +21,14 @@
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 
+#define IRQC_NMI			0
 #define IRQC_IRQ_START			1
 #define IRQC_TINT_COUNT			32
 #define IRQC_SHARED_IRQ_COUNT		8
 #define IRQC_IRQ_SHARED_START		(IRQC_IRQ_START + IRQC_SHARED_IRQ_COUNT)
 
+#define NSCR				0x0
+#define NITSR				0x4
 #define ISCR				0x10
 #define IITSR				0x14
 #define TSCR				0x20
@@ -44,6 +47,9 @@
 #define TSSR_OFFSET(n)			((n) % 4)
 #define TSSR_INDEX(n)			((n) / 4)
 
+#define NITSR_NTSEL_EDGE_FALLING	0
+#define NITSR_NTSEL_EDGE_RISING		1
+
 #define TITSR_TITSEL_EDGE_RISING	0
 #define TITSR_TITSEL_EDGE_FALLING	1
 #define TITSR_TITSEL_LEVEL_HIGH		2
@@ -64,11 +70,13 @@
 
 /**
  * struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume)
+ * @nitsr: NITSR register
  * @iitsr: IITSR register
  * @inttsel: INTTSEL register
  * @titsr: TITSR registers
  */
 struct rzg2l_irqc_reg_cache {
+	u32	nitsr;
 	u32	iitsr;
 	u32	inttsel;
 	u32	titsr[2];
@@ -117,6 +125,22 @@ static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
 	return data->domain->host_data;
 }
 
+static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
+{
+	u32 bit = BIT(hwirq);
+	u32 reg;
+
+	reg = readl_relaxed(priv->base + NSCR);
+	if (reg & bit) {
+		writel_relaxed(reg & ~bit, priv->base + NSCR);
+		/*
+		 * Enforce that the posted write is flushed to prevent that the
+		 * just handled interrupt is raised again.
+		 */
+		readl_relaxed(priv->base + NSCR);
+	}
+}
+
 static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
 {
 	unsigned int hw_irq = hwirq - IRQC_IRQ_START;
@@ -156,6 +180,17 @@ static void rzg2l_clear_tint_int(struct rzg2l_irqc_priv *priv, unsigned int hwir
 	}
 }
 
+static void rzg2l_irqc_nmi_eoi(struct irq_data *d)
+{
+	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
+	unsigned int hw_irq = irqd_to_hwirq(d);
+
+	scoped_guard(raw_spinlock, &priv->lock)
+		rzg2l_clear_nmi_int(priv, hw_irq);
+
+	irq_chip_eoi_parent(d);
+}
+
 static void rzg2l_irqc_irq_eoi(struct irq_data *d)
 {
 	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
@@ -342,6 +377,29 @@ static void rzg2l_irqc_tint_enable(struct irq_data *d)
 	irq_chip_enable_parent(d);
 }
 
+static int rzg2l_nmi_set_type(struct irq_data *d, unsigned int type)
+{
+	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
+	u32 sense;
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_FALLING:
+		sense = NITSR_NTSEL_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+		sense = NITSR_NTSEL_EDGE_RISING;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	writel_relaxed(sense, priv->base + NITSR);
+
+	return 0;
+}
+
 static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
@@ -468,11 +526,23 @@ static int rzg2l_irqc_tint_set_type(struct irq_data *d, unsigned int type)
 	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
 }
 
+static int rzg2l_irqc_nmi_set_type(struct irq_data *d, unsigned int type)
+{
+	int ret;
+
+	ret = rzg2l_nmi_set_type(d, type);
+	if (ret)
+		return ret;
+
+	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
+}
+
 static int rzg2l_irqc_irq_suspend(void *data)
 {
 	struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
 	void __iomem *base = rzg2l_irqc_data->base;
 
+	cache->nitsr = readl_relaxed(base + NITSR);
 	cache->iitsr = readl_relaxed(base + IITSR);
 	if (rzg2l_irqc_data->info.shared_irq_cnt)
 		cache->inttsel = readl_relaxed(base + INTTSEL);
@@ -497,6 +567,7 @@ static void rzg2l_irqc_irq_resume(void *data)
 	if (rzg2l_irqc_data->info.shared_irq_cnt)
 		writel_relaxed(cache->inttsel, base + INTTSEL);
 	writel_relaxed(cache->iitsr, base + IITSR);
+	writel_relaxed(cache->nitsr, base + NITSR);
 }
 
 static const struct syscore_ops rzg2l_irqc_syscore_ops = {
@@ -508,6 +579,23 @@ static struct syscore rzg2l_irqc_syscore = {
 	.ops = &rzg2l_irqc_syscore_ops,
 };
 
+static const struct irq_chip rzg2l_irqc_nmi_chip = {
+	.name			= "rzg2l-irqc",
+	.irq_eoi		= rzg2l_irqc_nmi_eoi,
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
+	.irq_disable		= irq_chip_disable_parent,
+	.irq_enable		= irq_chip_enable_parent,
+	.irq_get_irqchip_state	= irq_chip_get_parent_state,
+	.irq_set_irqchip_state	= irq_chip_set_parent_state,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_set_type		= rzg2l_irqc_nmi_set_type,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.flags			= IRQCHIP_MASK_ON_SUSPEND |
+				  IRQCHIP_SET_TYPE_MASKED |
+				  IRQCHIP_SKIP_SET_WAKE,
+};
+
 static const struct irq_chip rzg2l_irqc_irq_chip = {
 	.name			= "rzg2l-irqc",
 	.irq_eoi		= rzg2l_irqc_irq_eoi,
@@ -663,7 +751,9 @@ static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq,
 	 * from 16-31 bits. TINT from the pinctrl driver needs to be programmed
 	 * in IRQC registers to enable a given gpio pin as interrupt.
 	 */
-	if (hwirq > priv->info.irq_count) {
+	if (hwirq == IRQC_NMI) {
+		chip = &rzg2l_irqc_nmi_chip;
+	} else if (hwirq > priv->info.irq_count) {
 		tint = TINT_EXTRACT_GPIOINT(hwirq);
 		hwirq = TINT_EXTRACT_HWIRQ(hwirq);
 		chip = priv->tint_chip;
-- 
2.43.0


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

* [tip: irq/drivers] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type()
  2026-03-28 10:33 ` [PATCH 2/3] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type() Biju
@ 2026-03-28 13:20   ` tip-bot2 for Biju Das
  0 siblings, 0 replies; 13+ messages in thread
From: tip-bot2 for Biju Das @ 2026-03-28 13:20 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Biju Das, Thomas Gleixner, x86, linux-kernel

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

Commit-ID:     9fd2170d70178faa0427adaa9d2dfdbfa231d1b7
Gitweb:        https://git.kernel.org/tip/9fd2170d70178faa0427adaa9d2dfdbfa231d1b7
Author:        Biju Das <biju.das.jz@bp.renesas.com>
AuthorDate:    Sat, 28 Mar 2026 10:33:19 
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Sat, 28 Mar 2026 14:14:51 +01:00

irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type()

Simplify the locking logic in rzg2l_irq_set_type() by using guard(),
eliminating the need for an explicit unlock call.

[ tglx: Remove the pointless cleanup.h include. The spinlock guards come
  	from spinlock.h ]

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260328103324.134131-3-biju.das.jz@bp.renesas.com
---
 drivers/irqchip/irq-renesas-rzg2l.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index f5c4d7e..755fac3 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -373,14 +373,13 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	raw_spin_lock(&priv->lock);
+	guard(raw_spinlock)(&priv->lock);
 	tmp = readl_relaxed(priv->base + IITSR);
 	tmp &= ~IITSR_IITSEL_MASK(iitseln);
 	tmp |= IITSR_IITSEL(iitseln, sense);
 	if (clear_irq_int)
 		rzg2l_clear_irq_int(priv, hwirq);
 	writel_relaxed(tmp, priv->base + IITSR);
-	raw_spin_unlock(&priv->lock);
 
 	return 0;
 }

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

* Re: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-28 10:33 ` [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support Biju
@ 2026-03-28 16:19   ` Wolfram Sang
  2026-03-31 17:35     ` Biju Das
  2026-03-31 16:15   ` Thomas Gleixner
  1 sibling, 1 reply; 13+ messages in thread
From: Wolfram Sang @ 2026-03-28 16:19 UTC (permalink / raw)
  To: Biju
  Cc: Thomas Gleixner, Biju Das, linux-kernel, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 111 bytes --]


> +static const struct irq_chip rzg2l_irqc_nmi_chip = {
> +	.name			= "rzg2l-irqc",

"rzg2l-irqc-nmi" maybe?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-28 10:33 ` [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support Biju
  2026-03-28 16:19   ` Wolfram Sang
@ 2026-03-31 16:15   ` Thomas Gleixner
  2026-03-31 17:10     ` Biju Das
  1 sibling, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2026-03-31 16:15 UTC (permalink / raw)
  To: Biju
  Cc: Biju Das, linux-kernel, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	Biju Das, linux-renesas-soc

On Sat, Mar 28 2026 at 10:33, Biju wrote:
> +static void rzg2l_irqc_nmi_eoi(struct irq_data *d)
> +{
> +	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
> +	unsigned int hw_irq = irqd_to_hwirq(d);
> +
> +	scoped_guard(raw_spinlock, &priv->lock)
> +		rzg2l_clear_nmi_int(priv, hw_irq);

Is priv is shared between regular interrupts and the NMI?

If so, then you can't take the lock.

    // Some other context (task, interrupt)
    raw_spinlock(priv->lock);

--> NMI

        raw_spinlock(priv->lock);

--> Livelock.

Thanks,

        tglx

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

* RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-31 16:15   ` Thomas Gleixner
@ 2026-03-31 17:10     ` Biju Das
  2026-03-31 20:29       ` Thomas Gleixner
  0 siblings, 1 reply; 13+ messages in thread
From: Biju Das @ 2026-03-31 17:10 UTC (permalink / raw)
  To: Thomas Gleixner, biju.das.au
  Cc: linux-kernel@vger.kernel.org, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, biju.das.au,
	linux-renesas-soc@vger.kernel.org

Hi Thomas,

Thanks for the feedback.

> -----Original Message-----
> From: Thomas Gleixner <tglx@kernel.org>
> Sent: 31 March 2026 17:16
> Subject: Re: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
> 
> On Sat, Mar 28 2026 at 10:33, Biju wrote:
> > +static void rzg2l_irqc_nmi_eoi(struct irq_data *d) {
> > +	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
> > +	unsigned int hw_irq = irqd_to_hwirq(d);
> > +
> > +	scoped_guard(raw_spinlock, &priv->lock)
> > +		rzg2l_clear_nmi_int(priv, hw_irq);
> 
> Is priv is shared between regular interrupts and the NMI?

Yes.

> 
> If so, then you can't take the lock.

OK.

> 
>     // Some other context (task, interrupt)
>     raw_spinlock(priv->lock);
> 
> --> NMI
> 
>         raw_spinlock(priv->lock);
> 
> --> Livelock.

Will drop the lock as it is not RMW operation.

Cheers,
Biju

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

* [tip: irq/drivers] irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free()
  2026-03-28 10:33 ` [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free Biju
@ 2026-03-31 17:26   ` tip-bot2 for Biju Das
  0 siblings, 0 replies; 13+ messages in thread
From: tip-bot2 for Biju Das @ 2026-03-31 17:26 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Biju Das, Thomas Gleixner, x86, linux-kernel

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

Commit-ID:     d3689cd02c5de52ff5f3044169c482aee0dd5a78
Gitweb:        https://git.kernel.org/tip/d3689cd02c5de52ff5f3044169c482aee0dd5a78
Author:        Biju Das <biju.das.jz@bp.renesas.com>
AuthorDate:    Sat, 28 Mar 2026 10:33:18 
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Tue, 31 Mar 2026 18:25:29 +02:00

irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free()

rzg2l_irqc_free() invokes irq_domain_free_irqs_common(), which internally
calls irq_domain_reset_irq_data(). That explicitly sets irq_data->hwirq to
0. Consequently, irqd_to_hwirq(d) returns 0 when called after it.

Since 0 falls outside the valid shared IRQ ranges,
rzg2l_irqc_is_shared_and_get_irq_num() evaluates to false, completely
bypassing the test_and_clear_bit() operation.

This leaves the bit set in priv->used_irqs, causing future allocations to
fail with -EBUSY.

Fix this by retrieving irq_data and caching hwirq before calling
irq_domain_free_irqs_common().

Fixes: e0fcae27ff57 ("irqchip/renesas-rzg2l: Add shared interrupt support")
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260328103324.134131-2-biju.das.jz@bp.renesas.com
---
 drivers/irqchip/irq-renesas-rzg2l.c |  9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 755fac3..199b3c6 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -698,15 +698,14 @@ shared_irq_free:
 
 static void rzg2l_irqc_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)
 {
+	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 	struct rzg2l_irqc_priv *priv = domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	irq_domain_free_irqs_common(domain, virq, nr_irqs);
 
-	if (priv->info.shared_irq_cnt) {
-		struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-
-		rzg2l_irqc_shared_irq_free(priv, irqd_to_hwirq(d));
-	}
+	if (priv->info.shared_irq_cnt)
+		rzg2l_irqc_shared_irq_free(priv, hwirq);
 }
 
 static const struct irq_domain_ops rzg2l_irqc_domain_ops = {

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

* RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-28 16:19   ` Wolfram Sang
@ 2026-03-31 17:35     ` Biju Das
  0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2026-03-31 17:35 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Thomas Gleixner, linux-kernel@vger.kernel.org, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, linux-renesas-soc@vger.kernel.org

Hi Wolfram Sang,

Thanks for the feedback.

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 28 March 2026 16:19
> Subject: Re: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
> 
> 
> > +static const struct irq_chip rzg2l_irqc_nmi_chip = {
> > +	.name			= "rzg2l-irqc",
> 
> "rzg2l-irqc-nmi" maybe?

irq chip for tint and external interrupt are using "rzg2l-irqc"
for consistency "rzg2l-irqc" better compared to "rzg2l-irqc-nmi"

It reduces memory as a single pointer will be used in the
structure and also reduces number of changes.

Otherwise, we need to change

rzg2l-irqc-irq --> RZ/G2L irq interrupt
rzg2l-irqc-tint--> RZ/G2L tint interrupt
rzg2l-irqc-nmi --> RZ/{G2L,Five} nmi interrupt

rzfive-irqc-irq--> RZ/Five irq interrupt
rzfive-irqc-tint--> RZ/Five tint interrupt

Cheers,
Biju




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

* RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-31 17:10     ` Biju Das
@ 2026-03-31 20:29       ` Thomas Gleixner
  2026-04-01  7:30         ` Biju Das
  0 siblings, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2026-03-31 20:29 UTC (permalink / raw)
  To: Biju Das, biju.das.au
  Cc: linux-kernel@vger.kernel.org, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, biju.das.au,
	linux-renesas-soc@vger.kernel.org

On Tue, Mar 31 2026 at 17:10, Biju Das wrote:
>> From: Thomas Gleixner <tglx@kernel.org>
> Will drop the lock as it is not RMW operation.

Huch?

> +static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
> +{
> +	u32 bit = BIT(hwirq);
> +	u32 reg;
> +
> +	reg = readl_relaxed(priv->base + NSCR);
> +	if (reg & bit) {
> +		writel_relaxed(reg & ~bit, priv->base + NSCR);
> +		/*
> +		 * Enforce that the posted write is flushed to prevent that the
> +		 * just handled interrupt is raised again.
> +		 */
> +		readl_relaxed(priv->base + NSCR);
> +	}
> +}

How is that not RMW?

I assume that you want to explain that it's not a RMW on a shared
register, right?

Thanks,

        tglx

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

* RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-03-31 20:29       ` Thomas Gleixner
@ 2026-04-01  7:30         ` Biju Das
  2026-04-01 11:22           ` Thomas Gleixner
  0 siblings, 1 reply; 13+ messages in thread
From: Biju Das @ 2026-04-01  7:30 UTC (permalink / raw)
  To: Thomas Gleixner, biju.das.au
  Cc: linux-kernel@vger.kernel.org, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, biju.das.au,
	linux-renesas-soc@vger.kernel.org

Hi Thomas,

> -----Original Message-----
> From: Thomas Gleixner <tglx@kernel.org>
> Sent: 31 March 2026 21:30
> Subject: RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
> 
> On Tue, Mar 31 2026 at 17:10, Biju Das wrote:
> >> From: Thomas Gleixner <tglx@kernel.org>
> > Will drop the lock as it is not RMW operation.
> 
> Huch?
> 
> > +static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv,
> > +unsigned int hwirq) {
> > +	u32 bit = BIT(hwirq);
> > +	u32 reg;
> > +
> > +	reg = readl_relaxed(priv->base + NSCR);
> > +	if (reg & bit) {
> > +		writel_relaxed(reg & ~bit, priv->base + NSCR);
> > +		/*
> > +		 * Enforce that the posted write is flushed to prevent that the
> > +		 * just handled interrupt is raised again.
> > +		 */
> > +		readl_relaxed(priv->base + NSCR);
> > +	}
> > +}
> 
> How is that not RMW?

It is not a shared reg, as there is only a single NMI interrupt and hwirq is always 0.
I will drop BIT(hwirq) to avoid confusion related to the shared register.

> 
> I assume that you want to explain that it's not a RMW on a shared register, right?

Bit16 - NSMON: NMI pin signal level monitor register (read only)
Bit0 - NSTAT: NMI interrupt status. Writing is allowed only when NSTAT is 1.

Yes, I will add a comment: Writing is allowed only when NSTAT is 1.

Cheers,
Biju


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

* RE: [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support
  2026-04-01  7:30         ` Biju Das
@ 2026-04-01 11:22           ` Thomas Gleixner
  0 siblings, 0 replies; 13+ messages in thread
From: Thomas Gleixner @ 2026-04-01 11:22 UTC (permalink / raw)
  To: Biju Das, biju.das.au
  Cc: linux-kernel@vger.kernel.org, Geert Uytterhoeven,
	Prabhakar Mahadev Lad, biju.das.au,
	linux-renesas-soc@vger.kernel.org

On Wed, Apr 01 2026 at 07:30, Biju Das wrote:
>> From: Thomas Gleixner <tglx@kernel.org>
>> 
>> How is that not RMW?
>
> It is not a shared reg, as there is only a single NMI interrupt and hwirq is always 0.
> I will drop BIT(hwirq) to avoid confusion related to the shared register.
>
>> 
>> I assume that you want to explain that it's not a RMW on a shared register, right?
>
> Bit16 - NSMON: NMI pin signal level monitor register (read only)
> Bit0 - NSTAT: NMI interrupt status. Writing is allowed only when NSTAT is 1.
>
> Yes, I will add a comment: Writing is allowed only when NSTAT is 1.

Yes please.

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

end of thread, other threads:[~2026-04-01 11:22 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-28 10:33 [PATCH 0/3] irqchip/renesas-rzg2l: Bug fixes and NMI support Biju
2026-03-28 10:33 ` [PATCH 1/3] irqchip/renesas-rzg2l: Fix shared IRQ bit not cleared on free Biju
2026-03-31 17:26   ` [tip: irq/drivers] irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free() tip-bot2 for Biju Das
2026-03-28 10:33 ` [PATCH 2/3] irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type() Biju
2026-03-28 13:20   ` [tip: irq/drivers] " tip-bot2 for Biju Das
2026-03-28 10:33 ` [PATCH 3/3] irqchip/renesas-rzg2l: Add NMI support Biju
2026-03-28 16:19   ` Wolfram Sang
2026-03-31 17:35     ` Biju Das
2026-03-31 16:15   ` Thomas Gleixner
2026-03-31 17:10     ` Biju Das
2026-03-31 20:29       ` Thomas Gleixner
2026-04-01  7:30         ` Biju Das
2026-04-01 11:22           ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox