* [PATCH 0/2] Add MSI driver support for the Lightning Mountain SoC
@ 2026-03-18 13:10 Florian Eckert
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
0 siblings, 2 replies; 13+ messages in thread
From: Florian Eckert @ 2026-03-18 13:10 UTC (permalink / raw)
To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, Florian Eckert, Eckert.Florian, ms
The Lightning Mountain (LGM) does have an MSI irqchip connected to the
x86 vector domain. This series adds the driver and the devicetree binding
for this MSI IP core.
Maxlinear acquired Intel’s Home Gateway Platform Division (formerly Lantiq)
in 2020. The following SoCs do have this IP core [1].
* URX851
* URX850
The source files were extracted from the Maxlinear open-source kernel,
which is publicly available on GitHub [2].
[1] https://www.maxlinear.com/anywan
[2] https://github.com/maxlinear/linux/blob/updk_9.1.90/drivers/irqchip/irq-intel-soc-msi.c
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
Florian Eckert (2):
dt-bindings: Add Lightning Mountain MSI interrupt controller bindings
irqchip: Add Lightning Mountain irqchip support
.../interrupt-controller/intel,soc-msi.yaml | 45 +++
drivers/irqchip/Kconfig | 12 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-intel-soc-msi.c | 338 +++++++++++++++++++++
4 files changed, 396 insertions(+)
---
base-commit: f338e77383789c0cae23ca3d48adcc5e9e137e3c
change-id: 20260317-irq-intel-soc-msi-9637c760a1c0
Best regards,
--
Florian Eckert <fe@dev.tdt.de>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings
2026-03-18 13:10 [PATCH 0/2] Add MSI driver support for the Lightning Mountain SoC Florian Eckert
@ 2026-03-18 13:10 ` Florian Eckert
2026-03-18 14:46 ` Rob Herring (Arm)
` (2 more replies)
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
1 sibling, 3 replies; 13+ messages in thread
From: Florian Eckert @ 2026-03-18 13:10 UTC (permalink / raw)
To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, Florian Eckert, Eckert.Florian, ms
Add device tree bindings for the Lightning Mountain (LGM) MSI interrupt
controller.
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
.../interrupt-controller/intel,soc-msi.yaml | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5ab295c7dd000059817ae411abe3d57713a83ee8
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2025 TDT AG.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/intel,soc-msi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel LGM Interrupt Controller
+
+maintainers:
+ - Florian Eckert <fe@dev.tdt.de>
+
+description: |
+ This interrupt controller is found in the Intel LGM.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - intel,soc-msi.yaml
+
+ reg:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - interrupt-controller
+ - '#interrupt-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ soc_msi: soc_msi@e00e0000 {
+ compatible = "intel,soc-msi";
+ reg = <0xe00e0000 0x800>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-18 13:10 [PATCH 0/2] Add MSI driver support for the Lightning Mountain SoC Florian Eckert
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
@ 2026-03-18 13:10 ` Florian Eckert
2026-03-19 9:03 ` kernel test robot
` (3 more replies)
1 sibling, 4 replies; 13+ messages in thread
From: Florian Eckert @ 2026-03-18 13:10 UTC (permalink / raw)
To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, Florian Eckert, Eckert.Florian, ms
The Lightning Mountain (LGM) has a MSI irqchip connected to the x86 vector
domain. This commit adds the driver for this IP core, which is available on
the following SoCs from Maxlinear
* URX850
* URX851
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
drivers/irqchip/Kconfig | 12 ++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-intel-soc-msi.c | 338 ++++++++++++++++++++++++++++++++++++
3 files changed, 351 insertions(+)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index f07b00d7fef9078369a1dffb7ce414d37806d1c1..0acda52f65816ad85ee0a8b342aefdee12213716 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -826,4 +826,16 @@ config SUNPLUS_SP7021_INTC
chained controller, routing all interrupt source in P-Chip to
the primary controller on C-Chip.
+config INTEL_SOC_MSI
+ bool "Intel Lightning Mountain SoC MSI Support"
+ depends on OF && HAS_IOMEM
+ depends on ARCH_X86_64 || COMPILE_TEST
+ select GENERIC_MSI_IRQ_DOMAIN
+ help
+ Support for the Intel Lightning Mountain (LGM) SoC interrupt
+ controller. This is used as a chained controller. It´s parent is
+ the x86 vector domain.
+
+ If unsure, say N
+
endmenu
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 26aa3b6ec99fd4b45a0bfd8a934752d7295bfe8c..a2378d3ce298ea017733cc59b5b7441d8dac7b98 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_RISCV_APLIC) += irq-riscv-aplic-main.o irq-riscv-aplic-direct.o
obj-$(CONFIG_RISCV_APLIC_MSI) += irq-riscv-aplic-msi.o
obj-$(CONFIG_RISCV_IMSIC) += irq-riscv-imsic-state.o irq-riscv-imsic-early.o irq-riscv-imsic-platform.o
obj-$(CONFIG_RISCV_RPMI_SYSMSI) += irq-riscv-rpmi-sysmsi.o
+obj-$(CONFIG_INTEL_SOC_MSI) += irq-intel-soc-msi.o
obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o
obj-$(CONFIG_STARFIVE_JH8100_INTC) += irq-starfive-jh8100-intc.o
obj-$(CONFIG_ACLINT_SSWI) += irq-aclint-sswi.o
diff --git a/drivers/irqchip/irq-intel-soc-msi.c b/drivers/irqchip/irq-intel-soc-msi.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9cde15cf1247b75f145ef8368996ef3e1a9c21e
--- /dev/null
+++ b/drivers/irqchip/irq-intel-soc-msi.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Based on arch/x86/kernel/apic/msi.c and kernel/irq/msi.c
+ * Copyright (c) 2019 Intel Corporation.
+ * Copyright (c) 2020-2022, MaxLinear, Inc.
+ * Copyright (c) 2026 TDT AG.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/platform_device.h>
+
+#include <asm/irqdomain.h>
+#include <asm/apic.h>
+
+#define MSI_MSGA(x) ((x) << 2)
+#define MSI_MSGD(x) (0x200 + ((x) << 2))
+#define MSI_CTRL 0x400
+#define MSI_CTRL_EN BIT(0)
+#define MSI_MSK_L 0x404
+#define MSI_MSK_H 0x408
+
+#define NMI_MSI_47 47
+#define NMI_MSI_49 49
+#define NMI_MSI_62 62
+#define NMI_MSI_63 63
+
+#define MAX_SOC_MSI_IRQ_PINS 64
+
+struct soc_msi_dev {
+ struct device *dev;
+ void __iomem *base;
+ raw_spinlock_t lock; /* protect register handling */
+};
+
+struct soc_nmi_msi {
+ irq_hw_number_t irq;
+ int cpuid;
+};
+
+static const struct soc_nmi_msi nmi_msi[] = {
+ {NMI_MSI_47, 3},
+ {NMI_MSI_49, 2},
+ {NMI_MSI_62, 1},
+ {NMI_MSI_63, 0},
+ { },
+};
+
+static bool soc_nmi_msi(irq_hw_number_t hwirq)
+{
+ if (hwirq == NMI_MSI_47 || hwirq == NMI_MSI_49 ||
+ hwirq == NMI_MSI_62 || hwirq == NMI_MSI_63)
+ return true;
+
+ return false;
+}
+
+static u32 nmi_irq_to_cpuid(irq_hw_number_t hwirq)
+{
+ int i;
+ unsigned int nr_pcpus = num_possible_cpus();
+
+ for (i = 0; i < ARRAY_SIZE(nmi_msi); i++) {
+ if (nmi_msi[i].irq == hwirq) {
+ if (nmi_msi[i].cpuid >= nr_pcpus) {
+ WARN(1, "NMI on invalid CPU: cpu: %d\n",
+ nmi_msi[i].cpuid);
+ return -EINVAL;
+ }
+ return nmi_msi[i].cpuid;
+ }
+ }
+
+ WARN((i >= ARRAY_SIZE(nmi_msi)), "Should never come");
+
+ return -EINVAL;
+}
+
+static inline void
+soc_msi_update_bits(struct soc_msi_dev *mdev, u32 clr, u32 set, u32 ofs)
+{
+ writel((readl(mdev->base + ofs) & ~clr) | set, mdev->base + ofs);
+}
+
+static void soc_msi_enable(struct soc_msi_dev *mdev)
+{
+ soc_msi_update_bits(mdev, MSI_CTRL_EN, MSI_CTRL_EN, MSI_CTRL);
+}
+
+static void soc_msi_write_msg(struct irq_data *d, struct msi_msg *msg)
+{
+ struct soc_msi_dev *mdev = irq_data_get_irq_chip_data(d);
+ unsigned long flag;
+
+ raw_spin_lock_irqsave(&mdev->lock, flag);
+ writel(msg->address_lo, mdev->base + MSI_MSGA(d->hwirq));
+ writel(msg->data, mdev->base + MSI_MSGD(d->hwirq));
+ raw_spin_unlock_irqrestore(&mdev->lock, flag);
+}
+
+static void soc_msi_mask(struct irq_data *d)
+{
+ struct soc_msi_dev *mdev = irq_data_get_irq_chip_data(d);
+ unsigned long flag;
+ u32 off = d->hwirq < 32 ? MSI_MSK_L : MSI_MSK_H;
+
+ raw_spin_lock_irqsave(&mdev->lock, flag);
+ soc_msi_update_bits(mdev, 0, BIT(d->hwirq % 32), off);
+ raw_spin_unlock_irqrestore(&mdev->lock, flag);
+}
+
+static void soc_msi_unmask(struct irq_data *d)
+{
+ struct soc_msi_dev *mdev = irq_data_get_irq_chip_data(d);
+ unsigned long flag;
+ u32 off = d->hwirq < 32 ? MSI_MSK_L : MSI_MSK_H;
+
+ raw_spin_lock_irqsave(&mdev->lock, flag);
+ soc_msi_update_bits(mdev, BIT(d->hwirq % 32), 0, off);
+ raw_spin_unlock_irqrestore(&mdev->lock, flag);
+}
+
+static void nmi_msi_compose_msg(struct soc_msi_dev *mdev, irq_hw_number_t hwirq)
+{
+ struct msi_msg msg = {0};
+ unsigned long flag;
+ u32 cpuid, destid;
+ u32 off;
+
+ cpuid = nmi_irq_to_cpuid(hwirq);
+ if (cpuid < 0)
+ return;
+
+ destid = apic->calc_dest_apicid(cpuid);
+ off = hwirq < 32 ? MSI_MSK_L : MSI_MSK_H;
+
+ msg.arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
+ msg.arch_addr_lo.dest_mode_logical = apic->dest_mode_logical;
+ msg.arch_addr_lo.redirect_hint = 0;
+ msg.arch_addr_lo.destid_0_7 = destid & 0xFF;
+
+ msg.address_hi = X86_MSI_BASE_ADDRESS_HIGH;
+
+ /*
+ * On edge trigger, we don't care about assert level. Also,
+ * since delivery mode is NMI, no irq vector is needed.
+ */
+ msg.arch_data.is_level = 0;
+ msg.arch_data.delivery_mode = APIC_DELIVERY_MODE_NMI;
+
+ raw_spin_lock_irqsave(&mdev->lock, flag);
+ writel(msg.address_lo, mdev->base + MSI_MSGA(hwirq));
+ writel(msg.data, mdev->base + MSI_MSGD(hwirq));
+ soc_msi_update_bits(mdev, BIT(hwirq % 32), 0, off);
+ raw_spin_unlock_irqrestore(&mdev->lock, flag);
+}
+
+static void soc_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ __irq_msi_compose_msg(irqd_cfg(data), msg, false);
+}
+
+static struct irq_chip soc_msi_irq_chip = {
+ .name = "SOC-MSI",
+ .irq_unmask = soc_msi_unmask,
+ .irq_mask = soc_msi_mask,
+ .irq_ack = irq_chip_ack_parent,
+ .irq_set_affinity = msi_domain_set_affinity,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_compose_msi_msg = soc_msi_compose_msg,
+ .irq_write_msi_msg = soc_msi_write_msg,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int soc_msi_domain_xlate(struct irq_domain *d, struct irq_fwspec *fwspec,
+ unsigned long *hwirq, unsigned int *type)
+{
+ if (fwspec->param_count != 1)
+ return -EINVAL;
+
+ if (fwspec->param[0] > MAX_SOC_MSI_IRQ_PINS - 1)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+
+ return 0;
+}
+
+static int soc_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct msi_domain_info *msi_info = domain->host_data;
+ struct irq_fwspec *fwspec = arg;
+ struct irq_alloc_info info;
+ irq_hw_number_t hwirq;
+ unsigned int type;
+ void *chip_data;
+ int i, ret;
+
+ if (!msi_info)
+ return -EINVAL;
+
+ chip_data = msi_info->chip_data;
+
+ ret = soc_msi_domain_xlate(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ if (irq_find_mapping(domain, hwirq) > 0)
+ return -EEXIST;
+
+ /*
+ * All NMI interrupts go to vector 2, no irq mapping needed.
+ * What we want is to configure hardware once, don't do anything else.
+ * 0 means it will continue to initialize other stuff in the irqdomain.
+ * We can just return other value after hw initialized. In this case,
+ * irqdomain will release all resources.
+ */
+ if (soc_nmi_msi(hwirq)) {
+ nmi_msi_compose_msg((struct soc_msi_dev *)chip_data, hwirq);
+ return -EINVAL;
+ }
+
+ /* Translate to X86 favorite arguments */
+ init_irq_alloc_info(&info, NULL);
+
+ /* Need to allocate from x86 vector domain */
+ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &info);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < nr_irqs; i++) {
+ irq_domain_set_info(domain, virq + i, hwirq + i,
+ &soc_msi_irq_chip, chip_data,
+ handle_edge_irq, chip_data, "edge");
+ }
+
+ return 0;
+}
+
+static int soc_msi_domain_activate(struct irq_domain *domain,
+ struct irq_data *irq_data, bool early)
+{
+ struct msi_msg msg[2] = { [1] = { }, };
+
+ WARN_ON(irq_chip_compose_msi_msg(irq_data, msg));
+ soc_msi_write_msg(irq_data, msg);
+
+ return 0;
+}
+
+static void soc_msi_domain_deactivate(struct irq_domain *domain,
+ struct irq_data *irq_data)
+{
+ struct msi_msg msg[2];
+
+ memset(msg, 0, sizeof(msg));
+ soc_msi_write_msg(irq_data, msg);
+}
+
+static const struct irq_domain_ops soc_msi_domain_ops = {
+ .translate = soc_msi_domain_xlate,
+ .alloc = soc_msi_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+ .activate = soc_msi_domain_activate,
+ .deactivate = soc_msi_domain_deactivate,
+};
+
+static int intel_soc_msi_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct msi_domain_info *msi_info;
+ struct irq_domain *domain;
+ struct soc_msi_dev *mdev;
+ struct resource *res;
+
+ mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ return -ENOMEM;
+
+ msi_info = devm_kzalloc(&pdev->dev, sizeof(*msi_info), GFP_KERNEL);
+ if (!msi_info)
+ return -ENOMEM;
+
+ mdev->dev = &pdev->dev;
+
+ msi_info->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS;
+ msi_info->chip_data = mdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ mdev->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mdev->base)) {
+ dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
+ return PTR_ERR(mdev->base);
+ }
+
+ domain = irq_domain_create_hierarchy(x86_vector_domain, 0,
+ MAX_SOC_MSI_IRQ_PINS,
+ of_fwnode_handle(node),
+ &soc_msi_domain_ops, msi_info);
+
+ if (!domain) {
+ dev_err(&pdev->dev, "Failed to create soc_msi@%p irqdomain",
+ mdev->base);
+ return -ENOMEM;
+ }
+
+ raw_spin_lock_init(&mdev->lock);
+
+ platform_set_drvdata(pdev, mdev);
+
+ soc_msi_enable(mdev);
+
+ dev_info(&pdev->dev, "Intel SoC MSI init done\n");
+
+ return 0;
+}
+
+static const struct of_device_id of_intel_soc_msi_match[] = {
+ { .compatible = "intel,soc-msi" },
+ {}
+};
+
+static struct platform_driver intel_soc_msi_driver = {
+ .probe = intel_soc_msi_probe,
+ .driver = {
+ .name = "intel soc-msi",
+ .of_match_table = of_intel_soc_msi_match,
+ },
+};
+builtin_platform_driver(intel_soc_msi_driver);
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
@ 2026-03-18 14:46 ` Rob Herring (Arm)
2026-03-18 22:52 ` Rob Herring
2026-03-19 11:01 ` Krzysztof Kozlowski
2 siblings, 0 replies; 13+ messages in thread
From: Rob Herring (Arm) @ 2026-03-18 14:46 UTC (permalink / raw)
To: Florian Eckert
Cc: Thomas Gleixner, ms, devicetree, Conor Dooley,
Krzysztof Kozlowski, Eckert.Florian, linux-kernel
On Wed, 18 Mar 2026 14:10:40 +0100, Florian Eckert wrote:
> Add device tree bindings for the Lightning Mountain (LGM) MSI interrupt
> controller.
>
> Signed-off-by: Florian Eckert <fe@dev.tdt.de>
> ---
> .../interrupt-controller/intel,soc-msi.yaml | 45 ++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.example.dtb: /example-0/soc_msi@e00e0000: failed to match any schema with compatible: ['intel,soc-msi']
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20260318-irq-intel-soc-msi-v1-1-0e8cdf844fa8@dev.tdt.de
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
2026-03-18 14:46 ` Rob Herring (Arm)
@ 2026-03-18 22:52 ` Rob Herring
2026-03-19 11:01 ` Krzysztof Kozlowski
2 siblings, 0 replies; 13+ messages in thread
From: Rob Herring @ 2026-03-18 22:52 UTC (permalink / raw)
To: Florian Eckert
Cc: Thomas Gleixner, Krzysztof Kozlowski, Conor Dooley, linux-kernel,
devicetree, Eckert.Florian, ms
On Wed, Mar 18, 2026 at 02:10:40PM +0100, Florian Eckert wrote:
> Add device tree bindings for the Lightning Mountain (LGM) MSI interrupt
> controller.
>
> Signed-off-by: Florian Eckert <fe@dev.tdt.de>
> ---
> .../interrupt-controller/intel,soc-msi.yaml | 45 ++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..5ab295c7dd000059817ae411abe3d57713a83ee8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/intel,soc-msi.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +# Copyright 2025 TDT AG.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/interrupt-controller/intel,soc-msi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Intel LGM Interrupt Controller
> +
> +maintainers:
> + - Florian Eckert <fe@dev.tdt.de>
> +
> +description: |
Don't need '|' if no formatting.
> + This interrupt controller is found in the Intel LGM.
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - intel,soc-msi.yaml
Besides the obvious problem here, compatibles should be SoC specific.
> +
> + reg:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + '#interrupt-cells':
> + const: 2
This is an interrupt controller that generates MSIs from interrupts, or
an MSI controller that receives MSIs and generates an interrupt. I can't
tell. The description sounds like the latter. The schema looks like the
former.
> +
> +required:
> + - compatible
> + - reg
> + - interrupt-controller
> + - '#interrupt-cells'
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + soc_msi: soc_msi@e00e0000 {
msi-controller@... or interrupt-controller@...
depending on the above answer.
> + compatible = "intel,soc-msi";
> + reg = <0xe00e0000 0x800>;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
>
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
@ 2026-03-19 9:03 ` kernel test robot
2026-03-19 10:41 ` kernel test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2026-03-19 9:03 UTC (permalink / raw)
To: Florian Eckert, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: oe-kbuild-all, linux-kernel, devicetree, Florian Eckert,
Eckert.Florian, ms
Hi Florian,
kernel test robot noticed the following build errors:
[auto build test ERROR on f338e77383789c0cae23ca3d48adcc5e9e137e3c]
url: https://github.com/intel-lab-lkp/linux/commits/Florian-Eckert/dt-bindings-Add-Lightning-Mountain-MSI-interrupt-controller-bindings/20260319-033849
base: f338e77383789c0cae23ca3d48adcc5e9e137e3c
patch link: https://lore.kernel.org/r/20260318-irq-intel-soc-msi-v1-2-0e8cdf844fa8%40dev.tdt.de
patch subject: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20260319/202603191633.AoajEi81-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260319/202603191633.AoajEi81-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603191633.AoajEi81-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/irqchip/irq-intel-soc-msi.c:17:10: fatal error: asm/irqdomain.h: No such file or directory
17 | #include <asm/irqdomain.h>
| ^~~~~~~~~~~~~~~~~
compilation terminated.
vim +17 drivers/irqchip/irq-intel-soc-msi.c
16
> 17 #include <asm/irqdomain.h>
18 #include <asm/apic.h>
19
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
2026-03-19 9:03 ` kernel test robot
@ 2026-03-19 10:41 ` kernel test robot
2026-03-19 11:44 ` kernel test robot
2026-03-20 12:04 ` Thomas Gleixner
3 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2026-03-19 10:41 UTC (permalink / raw)
To: Florian Eckert, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: oe-kbuild-all, linux-kernel, devicetree, Florian Eckert,
Eckert.Florian, ms
Hi Florian,
kernel test robot noticed the following build warnings:
[auto build test WARNING on f338e77383789c0cae23ca3d48adcc5e9e137e3c]
url: https://github.com/intel-lab-lkp/linux/commits/Florian-Eckert/dt-bindings-Add-Lightning-Mountain-MSI-interrupt-controller-bindings/20260319-033849
base: f338e77383789c0cae23ca3d48adcc5e9e137e3c
patch link: https://lore.kernel.org/r/20260318-irq-intel-soc-msi-v1-2-0e8cdf844fa8%40dev.tdt.de
patch subject: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
config: um-allyesconfig (https://download.01.org/0day-ci/archive/20260319/202603191849.1i02oaur-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260319/202603191849.1i02oaur-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603191849.1i02oaur-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/irqchip/irq-intel-soc-msi.c: In function 'nmi_msi_compose_msg':
drivers/irqchip/irq-intel-soc-msi.c:138:18: error: 'apic' undeclared (first use in this function)
138 | destid = apic->calc_dest_apicid(cpuid);
| ^~~~
drivers/irqchip/irq-intel-soc-msi.c:138:18: note: each undeclared identifier is reported only once for each function it appears in
drivers/irqchip/irq-intel-soc-msi.c:141:25: error: 'arch_msi_msg_addr_lo_t' {aka 'struct arch_msi_msg_addr_lo'} has no member named 'base_address'
141 | msg.arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
| ^
drivers/irqchip/irq-intel-soc-msi.c:141:41: error: 'X86_MSI_BASE_ADDRESS_LOW' undeclared (first use in this function)
141 | msg.arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
| ^~~~~~~~~~~~~~~~~~~~~~~~
drivers/irqchip/irq-intel-soc-msi.c:142:25: error: 'arch_msi_msg_addr_lo_t' {aka 'struct arch_msi_msg_addr_lo'} has no member named 'dest_mode_logical'
142 | msg.arch_addr_lo.dest_mode_logical = apic->dest_mode_logical;
| ^
drivers/irqchip/irq-intel-soc-msi.c:143:25: error: 'arch_msi_msg_addr_lo_t' {aka 'struct arch_msi_msg_addr_lo'} has no member named 'redirect_hint'
143 | msg.arch_addr_lo.redirect_hint = 0;
| ^
drivers/irqchip/irq-intel-soc-msi.c:144:25: error: 'arch_msi_msg_addr_lo_t' {aka 'struct arch_msi_msg_addr_lo'} has no member named 'destid_0_7'
144 | msg.arch_addr_lo.destid_0_7 = destid & 0xFF;
| ^
drivers/irqchip/irq-intel-soc-msi.c:146:26: error: 'X86_MSI_BASE_ADDRESS_HIGH' undeclared (first use in this function)
146 | msg.address_hi = X86_MSI_BASE_ADDRESS_HIGH;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/irqchip/irq-intel-soc-msi.c:152:22: error: 'arch_msi_msg_data_t' {aka 'struct arch_msi_msg_data'} has no member named 'is_level'
152 | msg.arch_data.is_level = 0;
| ^
drivers/irqchip/irq-intel-soc-msi.c:153:22: error: 'arch_msi_msg_data_t' {aka 'struct arch_msi_msg_data'} has no member named 'delivery_mode'
153 | msg.arch_data.delivery_mode = APIC_DELIVERY_MODE_NMI;
| ^
drivers/irqchip/irq-intel-soc-msi.c:153:39: error: 'APIC_DELIVERY_MODE_NMI' undeclared (first use in this function)
153 | msg.arch_data.delivery_mode = APIC_DELIVERY_MODE_NMI;
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/irqchip/irq-intel-soc-msi.c: In function 'soc_msi_compose_msg':
drivers/irqchip/irq-intel-soc-msi.c:164:9: error: implicit declaration of function '__irq_msi_compose_msg'; did you mean 'nmi_msi_compose_msg'? [-Wimplicit-function-declaration]
164 | __irq_msi_compose_msg(irqd_cfg(data), msg, false);
| ^~~~~~~~~~~~~~~~~~~~~
| nmi_msi_compose_msg
drivers/irqchip/irq-intel-soc-msi.c:164:31: error: implicit declaration of function 'irqd_cfg' [-Wimplicit-function-declaration]
164 | __irq_msi_compose_msg(irqd_cfg(data), msg, false);
| ^~~~~~~~
drivers/irqchip/irq-intel-soc-msi.c: In function 'soc_msi_domain_alloc':
drivers/irqchip/irq-intel-soc-msi.c:198:31: error: storage size of 'info' isn't known
198 | struct irq_alloc_info info;
| ^~~~
drivers/irqchip/irq-intel-soc-msi.c:229:9: error: implicit declaration of function 'init_irq_alloc_info' [-Wimplicit-function-declaration]
229 | init_irq_alloc_info(&info, NULL);
| ^~~~~~~~~~~~~~~~~~~
>> drivers/irqchip/irq-intel-soc-msi.c:198:31: warning: unused variable 'info' [-Wunused-variable]
198 | struct irq_alloc_info info;
| ^~~~
drivers/irqchip/irq-intel-soc-msi.c: In function 'intel_soc_msi_probe':
drivers/irqchip/irq-intel-soc-msi.c:304:46: error: 'x86_vector_domain' undeclared (first use in this function)
304 | domain = irq_domain_create_hierarchy(x86_vector_domain, 0,
| ^~~~~~~~~~~~~~~~~
vim +/info +198 drivers/irqchip/irq-intel-soc-msi.c
192
193 static int soc_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
194 unsigned int nr_irqs, void *arg)
195 {
196 struct msi_domain_info *msi_info = domain->host_data;
197 struct irq_fwspec *fwspec = arg;
> 198 struct irq_alloc_info info;
199 irq_hw_number_t hwirq;
200 unsigned int type;
201 void *chip_data;
202 int i, ret;
203
204 if (!msi_info)
205 return -EINVAL;
206
207 chip_data = msi_info->chip_data;
208
209 ret = soc_msi_domain_xlate(domain, fwspec, &hwirq, &type);
210 if (ret)
211 return ret;
212
213 if (irq_find_mapping(domain, hwirq) > 0)
214 return -EEXIST;
215
216 /*
217 * All NMI interrupts go to vector 2, no irq mapping needed.
218 * What we want is to configure hardware once, don't do anything else.
219 * 0 means it will continue to initialize other stuff in the irqdomain.
220 * We can just return other value after hw initialized. In this case,
221 * irqdomain will release all resources.
222 */
223 if (soc_nmi_msi(hwirq)) {
224 nmi_msi_compose_msg((struct soc_msi_dev *)chip_data, hwirq);
225 return -EINVAL;
226 }
227
228 /* Translate to X86 favorite arguments */
229 init_irq_alloc_info(&info, NULL);
230
231 /* Need to allocate from x86 vector domain */
232 ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &info);
233 if (ret < 0)
234 return ret;
235
236 for (i = 0; i < nr_irqs; i++) {
237 irq_domain_set_info(domain, virq + i, hwirq + i,
238 &soc_msi_irq_chip, chip_data,
239 handle_edge_irq, chip_data, "edge");
240 }
241
242 return 0;
243 }
244
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
2026-03-18 14:46 ` Rob Herring (Arm)
2026-03-18 22:52 ` Rob Herring
@ 2026-03-19 11:01 ` Krzysztof Kozlowski
2 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-19 11:01 UTC (permalink / raw)
To: Florian Eckert, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-kernel, devicetree, Eckert.Florian, ms
On 18/03/2026 14:10, Florian Eckert wrote:
> Add device tree bindings for the Lightning Mountain (LGM) MSI interrupt
> controller.
Beside Rob's review:
Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
2026-03-19 9:03 ` kernel test robot
2026-03-19 10:41 ` kernel test robot
@ 2026-03-19 11:44 ` kernel test robot
2026-03-20 12:04 ` Thomas Gleixner
3 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2026-03-19 11:44 UTC (permalink / raw)
To: Florian Eckert, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: llvm, oe-kbuild-all, linux-kernel, devicetree, Florian Eckert,
Eckert.Florian, ms
Hi Florian,
kernel test robot noticed the following build errors:
[auto build test ERROR on f338e77383789c0cae23ca3d48adcc5e9e137e3c]
url: https://github.com/intel-lab-lkp/linux/commits/Florian-Eckert/dt-bindings-Add-Lightning-Mountain-MSI-interrupt-controller-bindings/20260319-033849
base: f338e77383789c0cae23ca3d48adcc5e9e137e3c
patch link: https://lore.kernel.org/r/20260318-irq-intel-soc-msi-v1-2-0e8cdf844fa8%40dev.tdt.de
patch subject: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260319/202603191903.MUNojwHX-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260319/202603191903.MUNojwHX-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603191903.MUNojwHX-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/irqchip/irq-intel-soc-msi.c:17:10: fatal error: 'asm/irqdomain.h' file not found
#include <asm/irqdomain.h>
^~~~~~~~~~~~~~~~~
1 error generated.
vim +17 drivers/irqchip/irq-intel-soc-msi.c
16
> 17 #include <asm/irqdomain.h>
18 #include <asm/apic.h>
19
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
` (2 preceding siblings ...)
2026-03-19 11:44 ` kernel test robot
@ 2026-03-20 12:04 ` Thomas Gleixner
2026-03-23 12:14 ` Florian Eckert
3 siblings, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2026-03-20 12:04 UTC (permalink / raw)
To: Florian Eckert, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, Florian Eckert, Eckert.Florian, ms,
Ricardo Neri
Florian!
On Wed, Mar 18 2026 at 14:10, Florian Eckert wrote:
> The Lightning Mountain (LGM) has a MSI irqchip connected to the x86 vector
> domain. This commit adds the driver for this IP core, which is available on
git grep 'This patch' Documentation/process.
It doesn't make it better when you replace patch with commit.
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Based on arch/x86/kernel/apic/msi.c and kernel/irq/msi.c
> + * Copyright (c) 2019 Intel Corporation.
> + * Copyright (c) 2020-2022, MaxLinear, Inc.
> + * Copyright (c) 2026 TDT AG.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/irq.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqdomain.h>
> +#include <linux/msi.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/irqdomain.h>
> +#include <asm/apic.h>
> +
> +#define MSI_MSGA(x) ((x) << 2)
> +#define MSI_MSGD(x) (0x200 + ((x) << 2))
> +#define MSI_CTRL 0x400
> +#define MSI_CTRL_EN BIT(0)
> +#define MSI_MSK_L 0x404
> +#define MSI_MSK_H 0x408
> +
> +#define NMI_MSI_47 47
> +#define NMI_MSI_49 49
> +#define NMI_MSI_62 62
> +#define NMI_MSI_63 63
> +
> +#define MAX_SOC_MSI_IRQ_PINS 64
> +
> +struct soc_msi_dev {
> + struct device *dev;
> + void __iomem *base;
> + raw_spinlock_t lock; /* protect register handling */
No tail comments please
> +};
> +
> +struct soc_nmi_msi {
> + irq_hw_number_t irq;
> + int cpuid;
unsigned int. We won't have negative CPU IDs in the forseeable future.
> +};
> +
> +static const struct soc_nmi_msi nmi_msi[] = {
> + {NMI_MSI_47, 3},
> + {NMI_MSI_49, 2},
> + {NMI_MSI_62, 1},
> + {NMI_MSI_63, 0},
> + { },
No C89 initializers and get rid of the pointless trailing {} entry.
> +};
> +
> +static bool soc_nmi_msi(irq_hw_number_t hwirq)
> +{
> + if (hwirq == NMI_MSI_47 || hwirq == NMI_MSI_49 ||
> + hwirq == NMI_MSI_62 || hwirq == NMI_MSI_63)
> + return true;
> +
> + return false;
> +}
> +
> +static u32 nmi_irq_to_cpuid(irq_hw_number_t hwirq)
> +{
> + int i;
> + unsigned int nr_pcpus = num_possible_cpus();
Variable declaration ordering. See
https://www.kernel.org/doc/html/latest/process/maintainer-tip.html
> + for (i = 0; i < ARRAY_SIZE(nmi_msi); i++) {
Now you use ARRAY_SIZE() which makes the trailing entry even more wrong.
> + if (nmi_msi[i].irq == hwirq) {
> + if (nmi_msi[i].cpuid >= nr_pcpus) {
> + WARN(1, "NMI on invalid CPU: cpu: %d\n",
> + nmi_msi[i].cpuid);
No line break required. You have 100 characters. But aside of that
this WARN() is bogus as the code path is well known already, no?
pr_warn() is sufficient.
> + return -EINVAL;
> + }
> + return nmi_msi[i].cpuid;
> + }
> + }
> +
> + WARN((i >= ARRAY_SIZE(nmi_msi)), "Should never come");
Ditto
> + return -EINVAL;
> +}
> +
> +static inline void
> +soc_msi_update_bits(struct soc_msi_dev *mdev, u32 clr, u32 set, u32 ofs)
s/ofs/offs/
> +{
> + writel((readl(mdev->base + ofs) & ~clr) | set, mdev->base + ofs);
> +}
> +
> +static void soc_msi_enable(struct soc_msi_dev *mdev)
> +{
> + soc_msi_update_bits(mdev, MSI_CTRL_EN, MSI_CTRL_EN, MSI_CTRL);
> +}
> +
> +static void soc_msi_write_msg(struct irq_data *d, struct msi_msg *msg)
> +{
> + struct soc_msi_dev *mdev = irq_data_get_irq_chip_data(d);
> + unsigned long flag;
> +
> + raw_spin_lock_irqsave(&mdev->lock, flag);
guard(raw_spinlock)(&mdev->lock);
There is no reason for irqsave as irq_write_msi_msg() is invoked with
the interrupt descriptor lock held, which implies interrupts are disabled.
> + writel(msg->address_lo, mdev->base + MSI_MSGA(d->hwirq));
> + writel(msg->data, mdev->base + MSI_MSGD(d->hwirq));
As the comment on top claims this was modelled after apic/msi.c I have
to ask the obvious question how this MSI incarnation is magically not
affected by the problem described in great length in msi_set_affinity().
> +static void nmi_msi_compose_msg(struct soc_msi_dev *mdev, irq_hw_number_t hwirq)
x86 lacks NMI support for irq domain based allocations....
> +{
> + struct msi_msg msg = {0};
> + unsigned long flag;
> + u32 cpuid, destid;
> + u32 off;
> +
> + cpuid = nmi_irq_to_cpuid(hwirq);
> + if (cpuid < 0)
> + return;
> +
> + destid = apic->calc_dest_apicid(cpuid);
> + off = hwirq < 32 ? MSI_MSK_L : MSI_MSK_H;
> +
> + msg.arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
> + msg.arch_addr_lo.dest_mode_logical = apic->dest_mode_logical;
> + msg.arch_addr_lo.redirect_hint = 0;
> + msg.arch_addr_lo.destid_0_7 = destid & 0xFF;
> +
> + msg.address_hi = X86_MSI_BASE_ADDRESS_HIGH;
> +
> + /*
> + * On edge trigger, we don't care about assert level. Also,
> + * since delivery mode is NMI, no irq vector is needed.
> + */
> + msg.arch_data.is_level = 0;
> + msg.arch_data.delivery_mode = APIC_DELIVERY_MODE_NMI;
> +
> + raw_spin_lock_irqsave(&mdev->lock, flag);
> + writel(msg.address_lo, mdev->base + MSI_MSGA(hwirq));
> + writel(msg.data, mdev->base + MSI_MSGD(hwirq));
> + soc_msi_update_bits(mdev, BIT(hwirq % 32), 0, off);
> + raw_spin_unlock_irqrestore(&mdev->lock, flag);
Writing the MSI message in compose_msg() smells more than fishy.
> +}
> +
> +
> +static int soc_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
> + unsigned int nr_irqs, void *arg)
> +{
> + struct msi_domain_info *msi_info = domain->host_data;
> + struct irq_fwspec *fwspec = arg;
> + struct irq_alloc_info info;
> + irq_hw_number_t hwirq;
> + unsigned int type;
> + void *chip_data;
> + int i, ret;
> +
> + if (!msi_info)
> + return -EINVAL;
> +
> + chip_data = msi_info->chip_data;
> +
> + ret = soc_msi_domain_xlate(domain, fwspec, &hwirq, &type);
> + if (ret)
> + return ret;
> +
> + if (irq_find_mapping(domain, hwirq) > 0)
> + return -EEXIST;
> +
> + /*
> + * All NMI interrupts go to vector 2, no irq mapping needed.
> + * What we want is to configure hardware once, don't do anything else.
> + * 0 means it will continue to initialize other stuff in the irqdomain.
> + * We can just return other value after hw initialized. In this case,
> + * irqdomain will release all resources.
This comment is incomprehensible word salad. Aside of that ...
> + */
> + if (soc_nmi_msi(hwirq)) {
> + nmi_msi_compose_msg((struct soc_msi_dev *)chip_data, hwirq);
> + return -EINVAL;
... this is a blatant violation of all layering rules known to mankind in
one go. Admittedly you get creativity points, but that's not making it
technically more correct.
> +static int soc_msi_domain_activate(struct irq_domain *domain,
> + struct irq_data *irq_data, bool early)
> +{
> + struct msi_msg msg[2] = { [1] = { }, };
> +
> + WARN_ON(irq_chip_compose_msi_msg(irq_data, msg));
> + soc_msi_write_msg(irq_data, msg);
> +
> + return 0;
That's just a copy of the corresponding kernel/irq/msi.c function.
> +}
> +
> +static void soc_msi_domain_deactivate(struct irq_domain *domain,
> + struct irq_data *irq_data)
> +{
> + struct msi_msg msg[2];
> +
> + memset(msg, 0, sizeof(msg));
> + soc_msi_write_msg(irq_data, msg);
Ditto.
> +}
> +
> +static const struct irq_domain_ops soc_msi_domain_ops = {
Now it's obvious why you need them. You are using the wrong interrupt
domain type.
> + .translate = soc_msi_domain_xlate,
> + .alloc = soc_msi_domain_alloc,
> + .free = irq_domain_free_irqs_common,
> + .activate = soc_msi_domain_activate,
> + .deactivate = soc_msi_domain_deactivate,
> +};
> +
> +static int intel_soc_msi_probe(struct platform_device *pdev)
> +{
> + struct device_node *node = pdev->dev.of_node;
> + struct msi_domain_info *msi_info;
> + struct irq_domain *domain;
> + struct soc_msi_dev *mdev;
> + struct resource *res;
> +
> + mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
> + if (!mdev)
> + return -ENOMEM;
> +
> + msi_info = devm_kzalloc(&pdev->dev, sizeof(*msi_info), GFP_KERNEL);
> + if (!msi_info)
> + return -ENOMEM;
> +
> + mdev->dev = &pdev->dev;
> +
> + msi_info->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS;
> + msi_info->chip_data = mdev;
Q: Does this magically create a MSI domain?
A: No
Q: Why?
A: Because irq_domain_create_hierarchy() will never reach the MSI code
that handles this.
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -EINVAL;
> +
> + mdev->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(mdev->base)) {
> + dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
> + return PTR_ERR(mdev->base);
> + }
> +
> + domain = irq_domain_create_hierarchy(x86_vector_domain, 0,
So this is hardwired to the vector domain and does not allow the
interrupts to be remapped? Those SoCs have VT-x which implies interrupt
remapping support. But what do I know about the infinite wisdom of
hardware designers.
TBH, if they decided to hardwire it to the vector domain, then they are
begging for a cluebat treatment.
Let me summarize what I can crystal-ball out of your comprehensive
change log and the insane amount of comments in the code:
1) The IP block converts 'wired' interrupts to MSI messages
2) It needs to route four interrupts as NMI
Right?
#1 The implementation gets the MSI interrupt domain concept completely
wrong
X86 uses the MSI parent domain concept.
[vector domain] -- [remap domain] -- [ device domain]
The remap domain is optional, but both the vector domain and the
remap domain act as MSI parent domains.
So what you want to create for that chip is a MSI device domain and
that domain needs to set the bus token to DOMAIN_BUS_WIRED_TO_MSI.
See drivers/irqchip/irq-mbigen.c mbigen_create_device_domain() and
related code as an example for a proper wired to MSI implementation.
#2 NMI routing
There has been attempts to implement that before in a clean way. The
patch set dried out, but the underlying changes for NMI support are
still valid and Ricardo (CC'ed) is working on them again, IIRC. See:
https://lore.kernel.org/lkml/20230301234753.28582-1-ricardo.neri-calderon@linux.intel.com/
Thanks,
tglx
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-20 12:04 ` Thomas Gleixner
@ 2026-03-23 12:14 ` Florian Eckert
2026-03-23 12:28 ` Ricardo Neri
2026-03-23 21:15 ` Thomas Gleixner
0 siblings, 2 replies; 13+ messages in thread
From: Florian Eckert @ 2026-03-23 12:14 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-kernel,
devicetree, Eckert.Florian, ms, Ricardo Neri
Hello Thomas,
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!res)
>> + return -EINVAL;
>> +
>> + mdev->base = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(mdev->base)) {
>> + dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
>> + return PTR_ERR(mdev->base);
>> + }
>> +
>> + domain = irq_domain_create_hierarchy(x86_vector_domain, 0,
>
> So this is hardwired to the vector domain and does not allow the
> interrupts to be remapped? Those SoCs have VT-x which implies interrupt
> remapping support. But what do I know about the infinite wisdom of
> hardware designers.
>
> TBH, if they decided to hardwire it to the vector domain, then they are
> begging for a cluebat treatment.
Unfortunately, I don’t have a detailed hardware description for this
IP block. All I have from the Maxlinear is this driver [1] from
their SDK.
> Let me summarize what I can crystal-ball out of your comprehensive
> change log and the insane amount of comments in the code:
>
> 1) The IP block converts 'wired' interrupts to MSI messages
>
> 2) It needs to route four interrupts as NMI
>
> Right?
It has a total of 64 IRQs. Four of these are connected to the
individual CPU cores as NMIs.
> #1 The implementation gets the MSI interrupt domain concept completely
> wrong
>
> X86 uses the MSI parent domain concept.
>
> [vector domain] -- [remap domain] -- [ device domain]
>
> The remap domain is optional, but both the vector domain and the
> remap domain act as MSI parent domains.
>
> So what you want to create for that chip is a MSI device domain and
> that domain needs to set the bus token to DOMAIN_BUS_WIRED_TO_MSI.
>
> See drivers/irqchip/irq-mbigen.c mbigen_create_device_domain() and
> related code as an example for a proper wired to MSI implementation.
Thanks for pointing that out. I’ll take a closer look at it this.
> #2 NMI routing
>
> There has been attempts to implement that before in a clean way. The
> patch set dried out, but the underlying changes for NMI support are
> still valid and Ricardo (CC'ed) is working on them again, IIRC. See:
>
>
> https://lore.kernel.org/lkml/20230301234753.28582-1-ricardo.neri-calderon@linux.intel.com/
The v7 is already about two years old – let’s see if there’s anything
else coming.
All in all, thank you for taking the time to look at this. I’ll go back
to the drawing board and have another closer look at it.
Thanks *all* for your feedback.
Best regards
Florian
[1]
https://github.com/maxlinear/linux/blob/updk_9.1.90/drivers/irqchip/irq-intel-soc-msi.c
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-23 12:14 ` Florian Eckert
@ 2026-03-23 12:28 ` Ricardo Neri
2026-03-23 21:15 ` Thomas Gleixner
1 sibling, 0 replies; 13+ messages in thread
From: Ricardo Neri @ 2026-03-23 12:28 UTC (permalink / raw)
To: Florian Eckert
Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-kernel, devicetree, Eckert.Florian, ms
On Mon, Mar 23, 2026 at 01:14:41PM +0100, Florian Eckert wrote:
> > #2 NMI routing
> >
> > There has been attempts to implement that before in a clean way. The
> > patch set dried out, but the underlying changes for NMI support are
> > still valid and Ricardo (CC'ed) is working on them again, IIRC. See:
> >
> >
> > https://lore.kernel.org/lkml/20230301234753.28582-1-ricardo.neri-calderon@linux.intel.com/
>
> The v7 is already about two years old – let’s see if there’s anything
> else coming.
That is correct. The series is old, but due to renewed interest I am working
on it again. I expect to post an updated series soon.
Thanks and BR,
Ricardo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support
2026-03-23 12:14 ` Florian Eckert
2026-03-23 12:28 ` Ricardo Neri
@ 2026-03-23 21:15 ` Thomas Gleixner
1 sibling, 0 replies; 13+ messages in thread
From: Thomas Gleixner @ 2026-03-23 21:15 UTC (permalink / raw)
To: Florian Eckert
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-kernel,
devicetree, Eckert.Florian, ms, Ricardo Neri
On Mon, Mar 23 2026 at 13:14, Florian Eckert wrote:
>>> + domain = irq_domain_create_hierarchy(x86_vector_domain, 0,
>>
>> So this is hardwired to the vector domain and does not allow the
>> interrupts to be remapped? Those SoCs have VT-x which implies interrupt
>> remapping support. But what do I know about the infinite wisdom of
>> hardware designers.
>>
>> TBH, if they decided to hardwire it to the vector domain, then they are
>> begging for a cluebat treatment.
>
> Unfortunately, I don’t have a detailed hardware description for this
> IP block. All I have from the Maxlinear is this driver [1] from
> their SDK.
Sigh.
>> #2 NMI routing
>>
>> There has been attempts to implement that before in a clean way. The
>> patch set dried out, but the underlying changes for NMI support are
>> still valid and Ricardo (CC'ed) is working on them again, IIRC. See:
>>
>> https://lore.kernel.org/lkml/20230301234753.28582-1-ricardo.neri-calderon@linux.intel.com/
>
> The v7 is already about two years old – let’s see if there’s anything
> else coming.
>
> All in all, thank you for taking the time to look at this. I’ll go back
> to the drawing board and have another closer look at it.
I'd start with the non-NMI part and by that time you got that going,
Ricardo might have an updated version ready.
Thanks,
tglx
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-03-23 21:16 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-18 13:10 [PATCH 0/2] Add MSI driver support for the Lightning Mountain SoC Florian Eckert
2026-03-18 13:10 ` [PATCH 1/2] dt-bindings: Add Lightning Mountain MSI interrupt controller bindings Florian Eckert
2026-03-18 14:46 ` Rob Herring (Arm)
2026-03-18 22:52 ` Rob Herring
2026-03-19 11:01 ` Krzysztof Kozlowski
2026-03-18 13:10 ` [PATCH 2/2] irqchip: Add Lightning Mountain irqchip support Florian Eckert
2026-03-19 9:03 ` kernel test robot
2026-03-19 10:41 ` kernel test robot
2026-03-19 11:44 ` kernel test robot
2026-03-20 12:04 ` Thomas Gleixner
2026-03-23 12:14 ` Florian Eckert
2026-03-23 12:28 ` Ricardo Neri
2026-03-23 21:15 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox