* [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support
@ 2026-05-12 18:46 Markus Stockhausen
2026-05-12 18:46 ` [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers Markus Stockhausen
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-05-12 18:46 UTC (permalink / raw)
To: tglx, linux-kernel; +Cc: Markus Stockhausen
The Realtek Otto switch series consists of multiple devices.
- RTL838x: single core (Realtek proprietary IRQ controller)
- RTL839x: multi core (Realtek proprietary IRQ controller)
- RTL930x: multi core (Realtek proprietary IRQ controller)
- RTL931x: multi core (MIPS GIC controller)
The first three devices are supported by the irq-realtek-rtl
driver. Until now it only supports single core operation. So
the multi core devices cannot be driven in SMP mode.
Add multi core support to the driver.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers
2026-05-12 18:46 [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
@ 2026-05-12 18:46 ` Markus Stockhausen
2026-06-03 15:57 ` Thomas Gleixner
2026-05-12 18:46 ` [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
2026-05-22 17:46 ` AW: [PATCH 0/2] " Markus Stockhausen
2 siblings, 1 reply; 9+ messages in thread
From: Markus Stockhausen @ 2026-05-12 18:46 UTC (permalink / raw)
To: tglx, linux-kernel; +Cc: Markus Stockhausen
The Realtek IRQ controller has two important registers that
are used by the driver in several places
- GIMR: global interrupt mask register
- IRR: Interrupt routing registers
The usage of these registers is very inconsistent. GIMR is
addressed directly while IRR has a helper that needs an
macro as an input. Harmonize this by providing consistent
helpers that improve code readability.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/irqchip/irq-realtek-rtl.c | 48 +++++++++++++++++++------------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 942c1f8c363d..7fb8dd4c5670 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -37,10 +37,29 @@ static void __iomem *realtek_ictl_base;
#define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32))
#define IRR_SHIFT(idx) ((idx * 4) % 32)
-static void write_irr(void __iomem *irr0, int idx, u32 value)
+static inline void enable_gimr(int hw_irq)
{
- unsigned int offset = IRR_OFFSET(idx);
- unsigned int shift = IRR_SHIFT(idx);
+ u32 gimr;
+
+ gimr = readl(REG(RTL_ICTL_GIMR));
+ gimr |= BIT(hw_irq);
+ writel(gimr, REG(RTL_ICTL_GIMR));
+}
+
+static inline void disable_gimr(int hwirq)
+{
+ u32 gimr;
+
+ gimr = readl(REG(RTL_ICTL_GIMR));
+ gimr &= ~BIT(hwirq);
+ writel(gimr, REG(RTL_ICTL_GIMR));
+}
+
+static void write_irr(int hw_irq, u32 value)
+{
+ void __iomem *irr0 = REG(RTL_ICTL_IRR0);
+ unsigned int offset = IRR_OFFSET(hw_irq);
+ unsigned int shift = IRR_SHIFT(hw_irq);
u32 irr;
irr = readl(irr0 + offset) & ~(0xf << shift);
@@ -51,28 +70,18 @@ static void write_irr(void __iomem *irr0, int idx, u32 value)
static void realtek_ictl_unmask_irq(struct irq_data *i)
{
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&irq_lock, flags);
-
- value = readl(REG(RTL_ICTL_GIMR));
- value |= BIT(i->hwirq);
- writel(value, REG(RTL_ICTL_GIMR));
-
+ enable_gimr(i->hwirq);
raw_spin_unlock_irqrestore(&irq_lock, flags);
}
static void realtek_ictl_mask_irq(struct irq_data *i)
{
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&irq_lock, flags);
-
- value = readl(REG(RTL_ICTL_GIMR));
- value &= ~BIT(i->hwirq);
- writel(value, REG(RTL_ICTL_GIMR));
-
+ disable_gimr(i->hwirq);
raw_spin_unlock_irqrestore(&irq_lock, flags);
}
@@ -89,7 +98,7 @@ static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
raw_spin_lock_irqsave(&irq_lock, flags);
- write_irr(REG(RTL_ICTL_IRR0), hw, 1);
+ write_irr(hw, 1);
raw_spin_unlock_irqrestore(&irq_lock, flags);
return 0;
@@ -135,9 +144,10 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
return -ENXIO;
/* Disable all cascaded interrupts and clear routing */
- writel(0, REG(RTL_ICTL_GIMR));
- for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++)
- write_irr(REG(RTL_ICTL_IRR0), soc_irq, 0);
+ for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) {
+ disable_gimr(soc_irq);
+ write_irr(soc_irq, 0);
+ }
if (WARN_ON(!of_irq_count(node))) {
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support
2026-05-12 18:46 [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
2026-05-12 18:46 ` [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers Markus Stockhausen
@ 2026-05-12 18:46 ` Markus Stockhausen
2026-06-03 16:02 ` Thomas Gleixner
2026-05-22 17:46 ` AW: [PATCH 0/2] " Markus Stockhausen
2 siblings, 1 reply; 9+ messages in thread
From: Markus Stockhausen @ 2026-05-12 18:46 UTC (permalink / raw)
To: tglx, linux-kernel; +Cc: Markus Stockhausen
The Realtek IRQ driver currently supports only single core
systems. So the higher end devices like RTL839x and RTL930x
with dual VPEs must be driven with NR_CPU=1. Enhance the
driver to support multicore (dual VPE) systems. For this:
- Extend the register map for multiple cores
- Search for multiple CPU cores in the devicetree
- Improve the register helpers to support multiple cores
- Add an affinity setter
- Enhance the IRQ handler for multiple cores
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/irqchip/irq-realtek-rtl.c | 91 +++++++++++++++++++++++--------
1 file changed, 69 insertions(+), 22 deletions(-)
diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 7fb8dd4c5670..e0e07074bf6f 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -23,10 +23,11 @@
#define RTL_ICTL_NUM_INPUTS 32
-#define REG(x) (realtek_ictl_base + x)
+#define REG(cpu, x) (realtek_ictl_base[cpu] + x)
static DEFINE_RAW_SPINLOCK(irq_lock);
-static void __iomem *realtek_ictl_base;
+static void __iomem *realtek_ictl_base[NR_CPUS];
+static cpumask_t realtek_ictl_cpu_configurable;
/*
* IRR0-IRR3 store 4 bits per interrupt, but Realtek uses inverted numbering,
@@ -37,27 +38,27 @@ static void __iomem *realtek_ictl_base;
#define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32))
#define IRR_SHIFT(idx) ((idx * 4) % 32)
-static inline void enable_gimr(int hw_irq)
+static inline void enable_gimr(int cpu, int hw_irq)
{
u32 gimr;
- gimr = readl(REG(RTL_ICTL_GIMR));
+ gimr = readl(REG(cpu, RTL_ICTL_GIMR));
gimr |= BIT(hw_irq);
- writel(gimr, REG(RTL_ICTL_GIMR));
+ writel(gimr, REG(cpu, RTL_ICTL_GIMR));
}
-static inline void disable_gimr(int hwirq)
+static inline void disable_gimr(int cpu, int hwirq)
{
u32 gimr;
- gimr = readl(REG(RTL_ICTL_GIMR));
+ gimr = readl(REG(cpu, RTL_ICTL_GIMR));
gimr &= ~BIT(hwirq);
- writel(gimr, REG(RTL_ICTL_GIMR));
+ writel(gimr, REG(cpu, RTL_ICTL_GIMR));
}
-static void write_irr(int hw_irq, u32 value)
+static void write_irr(int cpu, int hw_irq, u32 value)
{
- void __iomem *irr0 = REG(RTL_ICTL_IRR0);
+ void __iomem *irr0 = REG(cpu, RTL_ICTL_IRR0);
unsigned int offset = IRR_OFFSET(hw_irq);
unsigned int shift = IRR_SHIFT(hw_irq);
u32 irr;
@@ -70,35 +71,73 @@ static void write_irr(int hw_irq, u32 value)
static void realtek_ictl_unmask_irq(struct irq_data *i)
{
unsigned long flags;
+ cpumask_t cpus;
+ int cpu;
+
+ cpumask_and(&cpus, &realtek_ictl_cpu_configurable,
+ irq_data_get_effective_affinity_mask(i));
raw_spin_lock_irqsave(&irq_lock, flags);
- enable_gimr(i->hwirq);
+ for_each_cpu(cpu, &cpus)
+ enable_gimr(cpu, i->hwirq);
raw_spin_unlock_irqrestore(&irq_lock, flags);
}
static void realtek_ictl_mask_irq(struct irq_data *i)
{
unsigned long flags;
+ int cpu;
raw_spin_lock_irqsave(&irq_lock, flags);
- disable_gimr(i->hwirq);
+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
+ disable_gimr(cpu, i->hwirq);
raw_spin_unlock_irqrestore(&irq_lock, flags);
}
+static int realtek_ictl_irq_affinity(struct irq_data *i,
+ const struct cpumask *dest,
+ bool force)
+{
+ cpumask_t cpu_configure;
+ cpumask_t cpu_disable;
+ cpumask_t cpu_enable;
+ unsigned long flags;
+ int cpu;
+
+ cpumask_and(&cpu_configure, cpu_present_mask, &realtek_ictl_cpu_configurable);
+ cpumask_and(&cpu_enable, &cpu_configure, dest);
+ cpumask_andnot(&cpu_disable, &cpu_configure, dest);
+
+ raw_spin_lock_irqsave(&irq_lock, flags);
+ for_each_cpu(cpu, &cpu_disable)
+ disable_gimr(cpu, i->hwirq);
+ for_each_cpu(cpu, &cpu_enable)
+ if (!irqd_irq_masked(i))
+ enable_gimr(cpu, i->hwirq);
+ raw_spin_unlock_irqrestore(&irq_lock, flags);
+
+ irq_data_update_effective_affinity(i, &cpu_enable);
+
+ return IRQ_SET_MASK_OK;
+}
+
static struct irq_chip realtek_ictl_irq = {
.name = "realtek-rtl-intc",
.irq_mask = realtek_ictl_mask_irq,
.irq_unmask = realtek_ictl_unmask_irq,
+ .irq_set_affinity = realtek_ictl_irq_affinity,
};
static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
unsigned long flags;
+ int cpu;
irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
raw_spin_lock_irqsave(&irq_lock, flags);
- write_irr(hw, 1);
+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
+ write_irr(cpu, hw, 1);
raw_spin_unlock_irqrestore(&irq_lock, flags);
return 0;
@@ -112,12 +151,13 @@ static const struct irq_domain_ops irq_domain_ops = {
static void realtek_irq_dispatch(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
+ int cpu = smp_processor_id();
struct irq_domain *domain;
unsigned long pending;
unsigned int soc_int;
chained_irq_enter(chip, desc);
- pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
+ pending = readl(REG(cpu, RTL_ICTL_GIMR)) & readl(REG(cpu, RTL_ICTL_GISR));
if (unlikely(!pending)) {
spurious_interrupt();
@@ -139,16 +179,23 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
unsigned int soc_irq;
int parent_irq;
- realtek_ictl_base = of_iomap(node, 0);
- if (!realtek_ictl_base)
- return -ENXIO;
-
- /* Disable all cascaded interrupts and clear routing */
- for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) {
- disable_gimr(soc_irq);
- write_irr(soc_irq, 0);
+ cpumask_clear(&realtek_ictl_cpu_configurable);
+
+ for (int cpu = 0; cpu < NR_CPUS; cpu++) {
+ realtek_ictl_base[cpu] = of_iomap(node, cpu);
+ if (realtek_ictl_base[cpu]) {
+ cpumask_set_cpu(cpu, &realtek_ictl_cpu_configurable);
+ /* Disable all cascaded interrupts and clear routing */
+ for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) {
+ disable_gimr(cpu, soc_irq);
+ write_irr(cpu, soc_irq, 0);
+ }
+ }
}
+ if (cpumask_empty(&realtek_ictl_cpu_configurable))
+ return -ENXIO;
+
if (WARN_ON(!of_irq_count(node))) {
/*
* If DT contains no parent interrupts, assume MIPS CPU IRQ 2
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* AW: [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support
2026-05-12 18:46 [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
2026-05-12 18:46 ` [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers Markus Stockhausen
2026-05-12 18:46 ` [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
@ 2026-05-22 17:46 ` Markus Stockhausen
2 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-05-22 17:46 UTC (permalink / raw)
To: tglx, linux-kernel
Hi Thomas,
> Von: Markus Stockhausen <markus.stockhausen@gmx.de>
> Gesendet: Dienstag, 12. Mai 2026 20:47
> An: tglx@kernel.org; linux-kernel@vger.kernel.org
> Cc: Markus Stockhausen <markus.stockhausen@gmx.de>
> Betreff: [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support
>
> The Realtek Otto switch series consists of multiple devices.
>
> - RTL838x: single core (Realtek proprietary IRQ controller)
> - RTL839x: multi core (Realtek proprietary IRQ controller)
> - RTL930x: multi core (Realtek proprietary IRQ controller)
> - RTL931x: multi core (MIPS GIC controller)
>
> The first three devices are supported by the irq-realtek-rtl
> driver. Until now it only supports single core operation. So
> the multi core devices cannot be driven in SMP mode.
>
> Add multi core support to the driver.
Maybe you can give feedback on this series?
Thanks in advance.
Markus
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers
2026-05-12 18:46 ` [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers Markus Stockhausen
@ 2026-06-03 15:57 ` Thomas Gleixner
2026-06-04 12:32 ` AW: " Markus Stockhausen
0 siblings, 1 reply; 9+ messages in thread
From: Thomas Gleixner @ 2026-06-03 15:57 UTC (permalink / raw)
To: Markus Stockhausen, linux-kernel; +Cc: Markus Stockhausen
On Tue, May 12 2026 at 20:46, Markus Stockhausen wrote:
> The Realtek IRQ controller has two important registers that
s/IRQ/interrupt/
This is not a SMS service.
>
> -static void write_irr(void __iomem *irr0, int idx, u32 value)
> +static inline void enable_gimr(int hw_irq)
unsigned int hw_irq
> {
> - unsigned int offset = IRR_OFFSET(idx);
> - unsigned int shift = IRR_SHIFT(idx);
> + u32 gimr;
> +
> + gimr = readl(REG(RTL_ICTL_GIMR));
> + gimr |= BIT(hw_irq);
> + writel(gimr, REG(RTL_ICTL_GIMR));
> +}
> +
> +static inline void disable_gimr(int hwirq)
Ditto
> +{
> + u32 gimr;
> +
> + gimr = readl(REG(RTL_ICTL_GIMR));
> + gimr &= ~BIT(hwirq);
> + writel(gimr, REG(RTL_ICTL_GIMR));
> +}
> +
> +static void write_irr(int hw_irq, u32 value)
> +{
> + void __iomem *irr0 = REG(RTL_ICTL_IRR0);
> + unsigned int offset = IRR_OFFSET(hw_irq);
> + unsigned int shift = IRR_SHIFT(hw_irq);
> u32 irr;
>
> irr = readl(irr0 + offset) & ~(0xf << shift);
> @@ -51,28 +70,18 @@ static void write_irr(void __iomem *irr0, int idx, u32 value)
> static void realtek_ictl_unmask_irq(struct irq_data *i)
> {
> unsigned long flags;
> - u32 value;
>
> raw_spin_lock_irqsave(&irq_lock, flags);
Please convert that to
guard(raw_spinlock)(&lock);
while at it. No _irqsave required as mask/unmask are invoked with the
interrupt descriptor lock held and interrupts disabled.
> static void realtek_ictl_mask_irq(struct irq_data *i)
> {
> unsigned long flags;
> - u32 value;
>
> raw_spin_lock_irqsave(&irq_lock, flags);
Ditto
> -
> - value = readl(REG(RTL_ICTL_GIMR));
> - value &= ~BIT(i->hwirq);
> - writel(value, REG(RTL_ICTL_GIMR));
> -
> + disable_gimr(i->hwirq);
> raw_spin_unlock_irqrestore(&irq_lock, flags);
> }
>
> @@ -89,7 +98,7 @@ static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
> irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
>
guard(raw_spinlock_irq)(&lock);
_irq because this is task context.
> raw_spin_lock_irqsave(&irq_lock, flags);
> - write_irr(REG(RTL_ICTL_IRR0), hw, 1);
> + write_irr(hw, 1);
> raw_spin_unlock_irqrestore(&irq_lock, flags);
>
> return 0;
> @@ -135,9 +144,10 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
> return -ENXIO;
>
> /* Disable all cascaded interrupts and clear routing */
> - writel(0, REG(RTL_ICTL_GIMR));
> - for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++)
> - write_irr(REG(RTL_ICTL_IRR0), soc_irq, 0);
> + for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) {
Please make that
for (unsigned int soc_irq = 0; ....
and remove the declaration at the top of the function.
Thanks,
tglx
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support
2026-05-12 18:46 ` [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
@ 2026-06-03 16:02 ` Thomas Gleixner
2026-06-04 11:50 ` AW: " Markus Stockhausen
0 siblings, 1 reply; 9+ messages in thread
From: Thomas Gleixner @ 2026-06-03 16:02 UTC (permalink / raw)
To: Markus Stockhausen, linux-kernel; +Cc: Markus Stockhausen
On Tue, May 12 2026 at 20:46, Markus Stockhausen wrote:
> The Realtek IRQ driver currently supports only single core
s/IRQ/interrupt/g
> systems. So the higher end devices like RTL839x and RTL930x
> with dual VPEs must be driven with NR_CPU=1. Enhance the
> driver to support multicore (dual VPE) systems. For this:
>
> - Extend the register map for multiple cores
> - Search for multiple CPU cores in the devicetree
> - Improve the register helpers to support multiple cores
> - Add an affinity setter
> - Enhance the IRQ handler for multiple cores
>
>
> -static inline void enable_gimr(int hw_irq)
> +static inline void enable_gimr(int cpu, int hw_irq)
unsigned int cpu - All over the place.
> {
> u32 gimr;
>
> - gimr = readl(REG(RTL_ICTL_GIMR));
> + gimr = readl(REG(cpu, RTL_ICTL_GIMR));
> gimr |= BIT(hw_irq);
> - writel(gimr, REG(RTL_ICTL_GIMR));
> + writel(gimr, REG(cpu, RTL_ICTL_GIMR));
> }
>
> -static inline void disable_gimr(int hwirq)
> +static inline void disable_gimr(int cpu, int hwirq)
> {
> u32 gimr;
>
> - gimr = readl(REG(RTL_ICTL_GIMR));
> + gimr = readl(REG(cpu, RTL_ICTL_GIMR));
> gimr &= ~BIT(hwirq);
> - writel(gimr, REG(RTL_ICTL_GIMR));
> + writel(gimr, REG(cpu, RTL_ICTL_GIMR));
> }
>
> -static void write_irr(int hw_irq, u32 value)
> +static void write_irr(int cpu, int hw_irq, u32 value)
> {
> - void __iomem *irr0 = REG(RTL_ICTL_IRR0);
> + void __iomem *irr0 = REG(cpu, RTL_ICTL_IRR0);
> unsigned int offset = IRR_OFFSET(hw_irq);
> unsigned int shift = IRR_SHIFT(hw_irq);
> u32 irr;
> @@ -70,35 +71,73 @@ static void write_irr(int hw_irq, u32 value)
> static void realtek_ictl_unmask_irq(struct irq_data *i)
> {
> unsigned long flags;
> + cpumask_t cpus;
> + int cpu;
> +
> + cpumask_and(&cpus, &realtek_ictl_cpu_configurable,
> + irq_data_get_effective_affinity_mask(i));
What is this cpumask_and() for? The affinity setter already ensures that
the effective mask is a subset of configurable, no?
>
> +static int realtek_ictl_irq_affinity(struct irq_data *i,
> + const struct cpumask *dest,
> + bool force)
Please use the full 100 characters.
> +{
> + cpumask_t cpu_configure;
> + cpumask_t cpu_disable;
> + cpumask_t cpu_enable;
https://docs.kernel.org/process/maintainer-tip.html#variable-declarations
> + unsigned long flags;
> + int cpu;
> +
> + cpumask_and(&cpu_configure, cpu_present_mask, &realtek_ictl_cpu_configurable);
> + cpumask_and(&cpu_enable, &cpu_configure, dest);
> + cpumask_andnot(&cpu_disable, &cpu_configure, dest);
> +
> + raw_spin_lock_irqsave(&irq_lock, flags);
scoped_guard(raw_spinlock, ....) {
> + for_each_cpu(cpu, &cpu_disable)
> + disable_gimr(cpu, i->hwirq);
> + for_each_cpu(cpu, &cpu_enable)
> + if (!irqd_irq_masked(i))
> + enable_gimr(cpu, i->hwirq);
See bracket rules in the documentation I linked to.
}
> + raw_spin_unlock_irqrestore(&irq_lock, flags);
> +
> + irq_data_update_effective_affinity(i, &cpu_enable);
> +
> + return IRQ_SET_MASK_OK;
> +}
> +
> static struct irq_chip realtek_ictl_irq = {
> .name = "realtek-rtl-intc",
> .irq_mask = realtek_ictl_mask_irq,
> .irq_unmask = realtek_ictl_unmask_irq,
> + .irq_set_affinity = realtek_ictl_irq_affinity,
Please fix up the struct initializer according to documentation.
Thanks,
tglx
^ permalink raw reply [flat|nested] 9+ messages in thread
* AW: [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support
2026-06-03 16:02 ` Thomas Gleixner
@ 2026-06-04 11:50 ` Markus Stockhausen
0 siblings, 0 replies; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-04 11:50 UTC (permalink / raw)
To: 'Thomas Gleixner', linux-kernel
Hi Thomas,
thanks for the clear guidance and the notes about
using the proper locking functions. That simplified
the creation v2 of the series a lot.
Markus
^ permalink raw reply [flat|nested] 9+ messages in thread
* AW: [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers
2026-06-03 15:57 ` Thomas Gleixner
@ 2026-06-04 12:32 ` Markus Stockhausen
2026-06-04 12:39 ` Thomas Gleixner
0 siblings, 1 reply; 9+ messages in thread
From: Markus Stockhausen @ 2026-06-04 12:32 UTC (permalink / raw)
To: 'Thomas Gleixner'; +Cc: linux-kernel
> Von: Thomas Gleixner <tglx@kernel.org>
> Gesendet: Mittwoch, 3. Juni 2026 17:57
> An: Markus Stockhausen <markus.stockhausen@gmx.de>;
linux-kernel@vger.kernel.org
> Cc: Markus Stockhausen <markus.stockhausen@gmx.de>
> Betreff: Re: [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register
helpers
> ...
> > -
> > - value = readl(REG(RTL_ICTL_GIMR));
> > - value &= ~BIT(i->hwirq);
> > - writel(value, REG(RTL_ICTL_GIMR));
> > -
> > + disable_gimr(i->hwirq);
> > raw_spin_unlock_irqrestore(&irq_lock, flags);
> > }
> >
> > @@ -89,7 +98,7 @@ static int intc_map(struct irq_domain *d, unsigned int
irq, irq_hw_number_t hw)
> > irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
> >
> guard(raw_spinlock_irq)(&lock);
>
> _irq because this is task context.
>
> > raw_spin_lock_irqsave(&irq_lock, flags);
> > - write_irr(REG(RTL_ICTL_IRR0), hw, 1);
> > + write_irr(hw, 1);
> > raw_spin_unlock_irqrestore(&irq_lock, flags);
> >
> > return 0;
The above is the only one of your guides I'm unsure about.
With the whole series adapted and applied I finally get
static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t
hw)
{
unsigned int cpu;
irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
guard(raw_spinlock_irq)(&irq_lock);
for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
write_irr(cpu, hw, 1);
return 0;
}
Boot gives a warning.
[ 0.009035] ------------[ cut here ]------------
[ 0.014075] WARNING: CPU: 0 PID: 0 at init/main.c:1059
start_kernel+0x3a0/0x510
[ 0.022115] Interrupts were enabled early
[ 0.026483] Modules linked in:
[ 0.029846] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.18.33 #0
NONE
[ 0.029871] Hardware name: Linksys LGS328C
[ 0.029878] Stack : 80b7dddc 00000031 00000000 00000001 00000000 00000000
00000000 00000000
[ 0.029929] 00000000 00000000 00000000 00000000 00000000 00000001
80b7dd98 00000000
[ 0.029975] 00000000 00000000 80a846d4 80b7dc30 00000000 ffffefff
00000001 00000031
[ 0.030022] 00000033 80b7dbf4 00000033 00000264 00000001 00000000
80a846d4 80b7dea8
[ 0.030069] 00000000 80c23ec4 80b95238 80100000 00000000 80b9d4d0
00000000 813a0000
[ 0.030116] ...
[ 0.030125] Call Trace:
[ 0.030129] [<80114e38>] show_stack+0x28/0xf0
[ 0.030163] [<8010e0ec>] dump_stack_lvl+0x70/0xb0
[ 0.030197] [<801390cc>] __warn+0x9c/0x114
[ 0.030227] [<801392c4>] warn_slowpath_fmt+0x180/0x188
[ 0.030246] [<80c23ec4>] start_kernel+0x3a0/0x510
This goes away with switching to guard(raw_spinlock_irqsave)().
Anything I'm missing here?
Thanks in advance.
Markus
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: AW: [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers
2026-06-04 12:32 ` AW: " Markus Stockhausen
@ 2026-06-04 12:39 ` Thomas Gleixner
0 siblings, 0 replies; 9+ messages in thread
From: Thomas Gleixner @ 2026-06-04 12:39 UTC (permalink / raw)
To: Markus Stockhausen; +Cc: linux-kernel
On Thu, Jun 04 2026 at 14:32, Markus Stockhausen wrote:
>> Von: Thomas Gleixner <tglx@kernel.org>
>> Gesendet: Mittwoch, 3. Juni 2026 17:57
>> An: Markus Stockhausen <markus.stockhausen@gmx.de>;
> linux-kernel@vger.kernel.org
>> Cc: Markus Stockhausen <markus.stockhausen@gmx.de>
>> Betreff: Re: [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register
> helpers
>> ...
>> > -
>> > - value = readl(REG(RTL_ICTL_GIMR));
>> > - value &= ~BIT(i->hwirq);
>> > - writel(value, REG(RTL_ICTL_GIMR));
>> > -
>> > + disable_gimr(i->hwirq);
>> > raw_spin_unlock_irqrestore(&irq_lock, flags);
>> > }
>> >
>> > @@ -89,7 +98,7 @@ static int intc_map(struct irq_domain *d, unsigned int
> irq, irq_hw_number_t hw)
>> > irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
>> >
>> guard(raw_spinlock_irq)(&lock);
>>
>> _irq because this is task context.
>>
>> > raw_spin_lock_irqsave(&irq_lock, flags);
>> > - write_irr(REG(RTL_ICTL_IRR0), hw, 1);
>> > + write_irr(hw, 1);
>> > raw_spin_unlock_irqrestore(&irq_lock, flags);
>> >
>> > return 0;
>
> The above is the only one of your guides I'm unsure about.
> With the whole series adapted and applied I finally get
>
> static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t
> hw)
> {
> unsigned int cpu;
>
> irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
>
> guard(raw_spinlock_irq)(&irq_lock);
> for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
> write_irr(cpu, hw, 1);
>
> return 0;
> }
>
> Boot gives a warning.
Indeed. If map() is invoked during early boot, you need _irqsave.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-06-04 12:39 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-12 18:46 [PATCH 0/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
2026-05-12 18:46 ` [PATCH 1/2] irqchip/irq-realtek-rtl: Add/simplify register helpers Markus Stockhausen
2026-06-03 15:57 ` Thomas Gleixner
2026-06-04 12:32 ` AW: " Markus Stockhausen
2026-06-04 12:39 ` Thomas Gleixner
2026-05-12 18:46 ` [PATCH 2/2] irqchip/irq-realtek-rtl: Add multicore support Markus Stockhausen
2026-06-03 16:02 ` Thomas Gleixner
2026-06-04 11:50 ` AW: " Markus Stockhausen
2026-05-22 17:46 ` AW: [PATCH 0/2] " Markus Stockhausen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox