drivers/irqchip/irq-loongson-pch-lpc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
On certain Loongson platforms, drivers attempting to request a legacy
ISA IRQ directly via request_irq() (e.g., IRQ 4) may fail. The
virtual IRQ descriptor is not fully initialized and lacks a valid irqchip.
This issue does not affect ACPI-enumerated devices described in DSDT,
as their interrupts are properly mapped via the GSI translation path.
This indicates the LPC irqdomain itself is functional but is not correctly
handling direct VIRQ-to-HWIRQ mappings.
The root cause is the use of irq_domain_create_linear(). This API sets
up a domain for dynamic, on-demand mapping, typically triggered by a GSI
request. It does not pre-populate the mappings for the legacy VIRQ range
(0-15). Consequently, if no ACPI device claims a specific GSI
(e.g., GSI 4), the corresponding VIRQ (e.g., VIRQ 4) is never mapped to
the LPC domain. A direct call to request_irq(4, ...) then fails because
the kernel cannot resolve this VIRQ to a hardware interrupt managed by
the LPC controller.
The PCH-LPC interrupt controller is an i8259-compatible legacy device
that requires a deterministic, static 1-to-1 mapping for IRQs 0-15 to
support legacy drivers.
Fix this by replacing irq_domain_create_linear() with
irq_domain_create_legacy(). This API is specifically designed for such
controllers. It establishes the required static 1-to-1 VIRQ-to-HWIRQ
mapping for the entire legacy range (0-15) immediately upon domain
creation. This ensures that any VIRQ in this range is always resolvable,
making direct calls to request_irq() for legacy IRQs function correctly.
Signed-off-by: Ming Wang <wangming01@loongson.cn>
---
Changes in v2:
- Address review comments from Huacai Chen.
- Fix function call indentation style.
---
drivers/irqchip/irq-loongson-pch-lpc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c
index 2d4c3ec128b8..01fe4325ff84 100644
--- a/drivers/irqchip/irq-loongson-pch-lpc.c
+++ b/drivers/irqchip/irq-loongson-pch-lpc.c
@@ -200,8 +200,13 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
goto iounmap_base;
}
- priv->lpc_domain = irq_domain_create_linear(irq_handle, LPC_COUNT,
- &pch_lpc_domain_ops, priv);
+ /*
+ * The LPC interrupt controller is a legacy i8259-compatible device,
+ * which requires a static 1:1 mapping for IRQs 0-15.
+ * Use irq_domain_create_legacy() to establish this static mapping early.
+ */
+ priv->lpc_domain = irq_domain_create_legacy(irq_handle, LPC_COUNT, 0, 0,
+ &pch_lpc_domain_ops, priv);
if (!priv->lpc_domain) {
pr_err("Failed to create IRQ domain\n");
goto free_irq_handle;
--
2.43.0
On 9/11/25 16:35, Ming Wang wrote: > On certain Loongson platforms, drivers attempting to request a legacy > ISA IRQ directly via request_irq() (e.g., IRQ 4) may fail. The > virtual IRQ descriptor is not fully initialized and lacks a valid irqchip. > > This issue does not affect ACPI-enumerated devices described in DSDT, > as their interrupts are properly mapped via the GSI translation path. > This indicates the LPC irqdomain itself is functional but is not correctly > handling direct VIRQ-to-HWIRQ mappings. > > The root cause is the use of irq_domain_create_linear(). This API sets > up a domain for dynamic, on-demand mapping, typically triggered by a GSI > request. It does not pre-populate the mappings for the legacy VIRQ range > (0-15). Consequently, if no ACPI device claims a specific GSI > (e.g., GSI 4), the corresponding VIRQ (e.g., VIRQ 4) is never mapped to > the LPC domain. A direct call to request_irq(4, ...) then fails because > the kernel cannot resolve this VIRQ to a hardware interrupt managed by > the LPC controller. > > The PCH-LPC interrupt controller is an i8259-compatible legacy device > that requires a deterministic, static 1-to-1 mapping for IRQs 0-15 to > support legacy drivers. > > Fix this by replacing irq_domain_create_linear() with > irq_domain_create_legacy(). This API is specifically designed for such > controllers. It establishes the required static 1-to-1 VIRQ-to-HWIRQ > mapping for the entire legacy range (0-15) immediately upon domain > creation. This ensures that any VIRQ in this range is always resolvable, > making direct calls to request_irq() for legacy IRQs function correctly. > > Signed-off-by: Ming Wang <wangming01@loongson.cn> I have tested this patch on a Loongson 3A6000 platform. Tested-by: Robin <robin.toplinux@gmail.com> > > --- > Changes in v2: > - Address review comments from Huacai Chen. > - Fix function call indentation style. > --- > drivers/irqchip/irq-loongson-pch-lpc.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c > index 2d4c3ec128b8..01fe4325ff84 100644 > --- a/drivers/irqchip/irq-loongson-pch-lpc.c > +++ b/drivers/irqchip/irq-loongson-pch-lpc.c > @@ -200,8 +200,13 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, > goto iounmap_base; > } > > - priv->lpc_domain = irq_domain_create_linear(irq_handle, LPC_COUNT, > - &pch_lpc_domain_ops, priv); > + /* > + * The LPC interrupt controller is a legacy i8259-compatible device, > + * which requires a static 1:1 mapping for IRQs 0-15. > + * Use irq_domain_create_legacy() to establish this static mapping early. > + */ > + priv->lpc_domain = irq_domain_create_legacy(irq_handle, LPC_COUNT, 0, 0, > + &pch_lpc_domain_ops, priv); > if (!priv->lpc_domain) { > pr_err("Failed to create IRQ domain\n"); > goto free_irq_handle;
On Thu, Sep 11, 2025 at 4:35 PM Ming Wang <wangming01@loongson.cn> wrote: > > On certain Loongson platforms, drivers attempting to request a legacy > ISA IRQ directly via request_irq() (e.g., IRQ 4) may fail. The > virtual IRQ descriptor is not fully initialized and lacks a valid irqchip. > > This issue does not affect ACPI-enumerated devices described in DSDT, > as their interrupts are properly mapped via the GSI translation path. > This indicates the LPC irqdomain itself is functional but is not correctly > handling direct VIRQ-to-HWIRQ mappings. > > The root cause is the use of irq_domain_create_linear(). This API sets > up a domain for dynamic, on-demand mapping, typically triggered by a GSI > request. It does not pre-populate the mappings for the legacy VIRQ range > (0-15). Consequently, if no ACPI device claims a specific GSI > (e.g., GSI 4), the corresponding VIRQ (e.g., VIRQ 4) is never mapped to > the LPC domain. A direct call to request_irq(4, ...) then fails because > the kernel cannot resolve this VIRQ to a hardware interrupt managed by > the LPC controller. > > The PCH-LPC interrupt controller is an i8259-compatible legacy device > that requires a deterministic, static 1-to-1 mapping for IRQs 0-15 to > support legacy drivers. > > Fix this by replacing irq_domain_create_linear() with > irq_domain_create_legacy(). This API is specifically designed for such > controllers. It establishes the required static 1-to-1 VIRQ-to-HWIRQ > mapping for the entire legacy range (0-15) immediately upon domain > creation. This ensures that any VIRQ in this range is always resolvable, > making direct calls to request_irq() for legacy IRQs function correctly. > > Signed-off-by: Ming Wang <wangming01@loongson.cn> Reviewed-by: Huacai Chen <chenhuacai@loongson.cn> > > --- > Changes in v2: > - Address review comments from Huacai Chen. > - Fix function call indentation style. > --- > drivers/irqchip/irq-loongson-pch-lpc.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c > index 2d4c3ec128b8..01fe4325ff84 100644 > --- a/drivers/irqchip/irq-loongson-pch-lpc.c > +++ b/drivers/irqchip/irq-loongson-pch-lpc.c > @@ -200,8 +200,13 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent, > goto iounmap_base; > } > > - priv->lpc_domain = irq_domain_create_linear(irq_handle, LPC_COUNT, > - &pch_lpc_domain_ops, priv); > + /* > + * The LPC interrupt controller is a legacy i8259-compatible device, > + * which requires a static 1:1 mapping for IRQs 0-15. > + * Use irq_domain_create_legacy() to establish this static mapping early. > + */ > + priv->lpc_domain = irq_domain_create_legacy(irq_handle, LPC_COUNT, 0, 0, > + &pch_lpc_domain_ops, priv); > if (!priv->lpc_domain) { > pr_err("Failed to create IRQ domain\n"); > goto free_irq_handle; > -- > 2.43.0 >
© 2016 - 2025 Red Hat, Inc.