The AST2700 interrupt fabric is shared by multiple integrated processors
(PSP/SSP/TSP/BootMCU), each with its own interrupt controller and its own
devicetree view of the system. As a result, interrupt routing cannot be
treated as fixed: the valid route for a peripheral interrupt depends on
which processor is consuming it.
The INTC0 driver models this by creating a hierarchical irqdomain under
the upstream interrupt controller selected by the interrupt-parent
property in the devicetree. Information derived from this relationship
is incorporated into the route resolution logic for the controller.
The INTC1 driver implements the banked INTM-fed controller and forwards
interrupts toward INTC0, without embedding assumptions about the final
destination processor.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
drivers/irqchip/Kconfig | 11 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-ast2700-intc0-test.c | 474 +++++++++++++++++++
drivers/irqchip/irq-ast2700-intc0.c | 770 +++++++++++++++++++++++++++++++
drivers/irqchip/irq-ast2700-intc1.c | 345 ++++++++++++++
drivers/irqchip/irq-ast2700.c | 105 +++++
drivers/irqchip/irq-ast2700.h | 37 ++
7 files changed, 1743 insertions(+)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index f334f49c9791..3cc0f3af0e1e 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -110,6 +110,17 @@ config AL_FIC
help
Support Amazon's Annapurna Labs Fabric Interrupt Controller.
+config ASPEED_AST2700_INTC
+ bool "ASPEED AST2700 Interrupt Controller support"
+ depends on OF
+ depends on ARCH_ASPEED || COMPILE_TEST
+ select IRQ_DOMAIN_HIERARCHY
+
+config ASPEED_AST2700_INTC_TEST
+ bool "Tests for the ASPEED AST2700 Interrupt Controller"
+ depends on ASPEED_AST2700_INTC && KUNIT=y
+ default KUNIT_ALL_TESTS
+
config ATMEL_AIC_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 6a229443efe0..51fdf269e436 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o
obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
+obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o irq-ast2700-intc0.o irq-ast2700-intc1.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o
obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o
diff --git a/drivers/irqchip/irq-ast2700-intc0-test.c b/drivers/irqchip/irq-ast2700-intc0-test.c
new file mode 100644
index 000000000000..d6bc19676b2e
--- /dev/null
+++ b/drivers/irqchip/irq-ast2700-intc0-test.c
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Code Construct
+ */
+#include <kunit/test.h>
+#include "irq-ast2700.h"
+
+static void aspeed_intc0_resolve_route_bad_args(struct kunit *test)
+{
+ static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ const struct irq_domain c0domain = { 0 };
+
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL);
+ KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+
+ rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, -ENODEV);
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ 0, c1ranges, &resolved);
+ KUNIT_EXPECT_EQ(test, rc, -ENODEV);
+}
+
+static int
+arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle,
+ const char *propname, const char **val,
+ size_t nval)
+{
+ if (!propname)
+ return -EINVAL;
+
+ if (!val)
+ return 1;
+
+ if (WARN_ON(nval != 1))
+ return -EOVERFLOW;
+
+ *val = "arm,gic-v3";
+ return 1;
+}
+
+static const struct fwnode_operations arm_gicv3_fwnode_ops = {
+ .property_read_string_array = arm_gicv3_fwnode_read_string_array,
+};
+
+static void aspeed_intc_resolve_route_invalid_c0domain(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &arm_gicv3_fwnode_ops },
+ };
+ const struct irq_domain c0domain = { .fwnode = &intc0_node.fwnode };
+ static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_NE(test, rc, 0);
+}
+
+static int
+aspeed_intc0_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle,
+ const char *propname, const char **val,
+ size_t nval)
+{
+ if (!propname)
+ return -EINVAL;
+
+ if (!val)
+ return 1;
+
+ if (WARN_ON(nval != 1))
+ return -EOVERFLOW;
+
+ *val = "aspeed,ast2700-intc0-ic";
+ return nval;
+}
+
+static const struct fwnode_operations intc0_fwnode_ops = {
+ .property_read_string_array = aspeed_intc0_fwnode_read_string_array,
+};
+
+static void
+aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 128 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 128,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = { .ranges = intc0_ranges, .nranges = ARRAY_SIZE(intc0_ranges), }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, 0);
+ KUNIT_EXPECT_EQ(test, resolved.start, 0);
+ KUNIT_EXPECT_EQ(test, resolved.count, 1);
+ KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 128);
+}
+
+static void
+aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 128 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 129,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_NE(test, rc, 0);
+}
+
+static void aspeed_intc0_resolve_route_c1i1o1mc0i1o1(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 480 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 192,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, 0);
+ KUNIT_EXPECT_EQ(test, resolved.start, 0);
+ KUNIT_EXPECT_EQ(test, resolved.count, 1);
+ KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480);
+}
+
+static void aspeed_intc0_resolve_route_c1i2o2mc0i1o1(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 480 }
+ }
+ },
+ {
+ .start = 1,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 510 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = { 1 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 208,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, 0);
+ KUNIT_EXPECT_EQ(test, resolved.start, 1);
+ KUNIT_EXPECT_EQ(test, resolved.count, 1);
+ KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510);
+}
+
+static void aspeed_intc0_resolve_route_c1i1o1mc0i2o1(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 510 }
+ }
+ },
+ };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 192,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = {0},
+ }
+ },
+ {
+ .start = 208,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = {0},
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, 0);
+ KUNIT_EXPECT_EQ(test, resolved.start, 0);
+ KUNIT_EXPECT_EQ(test, resolved.count, 1);
+ KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510);
+}
+
+static void aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 1,
+ .param = { 480 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = {
+ AST2700_INTC_INVALID_ROUTE, 0
+ };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 192,
+ .count = 1,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_EQ(test, rc, 1);
+ KUNIT_EXPECT_EQ(test, resolved.start, 0);
+ KUNIT_EXPECT_EQ(test, resolved.count, 1);
+ KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480);
+}
+
+static void
+aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream(struct kunit *test)
+{
+ struct device_node intc0_node = {
+ .fwnode = { .ops = &intc0_fwnode_ops },
+ };
+ struct aspeed_intc_interrupt_range c1ranges[] = {
+ {
+ .start = 0,
+ .count = 1,
+ .upstream = {
+ .fwnode = &intc0_node.fwnode,
+ .param_count = 0,
+ .param = { 0 }
+ }
+ }
+ };
+ static const aspeed_intc_output_t c1outs[] = { 0 };
+ struct aspeed_intc_interrupt_range resolved;
+ struct aspeed_intc_interrupt_range intc0_ranges[] = {
+ {
+ .start = 0,
+ .count = 0,
+ .upstream = {
+ .fwnode = NULL,
+ .param_count = 0,
+ .param = { 0 },
+ }
+ }
+ };
+ struct aspeed_intc0 intc0 = {
+ .ranges = {
+ .ranges = intc0_ranges,
+ .nranges = ARRAY_SIZE(intc0_ranges),
+ }
+ };
+ const struct irq_domain c0domain = {
+ .host_data = &intc0,
+ .fwnode = &intc0_node.fwnode
+ };
+ int rc;
+
+ rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
+ ARRAY_SIZE(c1ranges), c1ranges,
+ &resolved);
+ KUNIT_EXPECT_NE(test, rc, 0);
+}
+
+static struct kunit_case ast2700_intc0_test_cases[] = {
+ KUNIT_CASE(aspeed_intc0_resolve_route_bad_args),
+ KUNIT_CASE(aspeed_intc_resolve_route_invalid_c0domain),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i2o2mc0i1o1),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i2o1),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid),
+ KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream),
+ {},
+};
+
+static struct kunit_suite ast2700_intc0_test_suite = {
+ .name = "ast2700-intc0",
+ .test_cases = ast2700_intc0_test_cases,
+};
+kunit_test_suite(ast2700_intc0_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/irqchip/irq-ast2700-intc0.c b/drivers/irqchip/irq-ast2700-intc0.c
new file mode 100644
index 000000000000..722457dd2e18
--- /dev/null
+++ b/drivers/irqchip/irq-ast2700-intc0.c
@@ -0,0 +1,770 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Aspeed Interrupt Controller.
+ *
+ * Copyright (C) 2023 ASPEED Technology Inc.
+ */
+
+#include <asm-generic/errno.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/fwnode.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kconfig.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/property.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "irq-ast2700.h"
+#define INT_NUM 480
+#define INTM_NUM 50
+#define SWINT_NUM 16
+
+#define INTM_BASE (INT_NUM)
+#define SWINT_BASE (INT_NUM + INTM_NUM)
+#define INT0_NUM (INT_NUM + INTM_NUM + SWINT_NUM)
+
+#define GIC_P2P_SPI_END 128
+
+#define INTC0_SWINT_IER 0x10
+#define INTC0_SWINT_ISR 0x14
+#define INTC0_INTBANKX_IER 0x1000
+#define INTC0_INTBANK_GROUPS 11
+#define INTC0_INTBANKS_PER_GRP 3
+#define INTC0_INTMX_IER 0x1b00
+#define INTC0_INTMX_ISR 0x1b04
+#define INTC0_INTM_BANK_NUM 3
+#define INTM_IRQS_PER_BANK 10
+
+struct aspeed_intc0 {
+ struct device *dev;
+ void __iomem *base;
+ raw_spinlock_t intc_lock;
+ struct irq_domain *local;
+ struct device_node *parent;
+ struct aspeed_intc_interrupt_ranges ranges;
+};
+
+static void aspeed_swint_irq_mask(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bit = data->hwirq - SWINT_BASE;
+ unsigned int mask;
+
+ guard(raw_spinlock_irqsave)(&intc0->intc_lock);
+ mask = readl(intc0->base + INTC0_SWINT_IER) & ~BIT(bit);
+ writel(mask, intc0->base + INTC0_SWINT_IER);
+ irq_chip_mask_parent(data);
+}
+
+static void aspeed_swint_irq_unmask(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bit = data->hwirq - SWINT_BASE;
+ unsigned int unmask;
+
+ guard(raw_spinlock_irqsave)(&intc0->intc_lock);
+ unmask = readl(intc0->base + INTC0_SWINT_IER) | BIT(bit);
+ writel(unmask, intc0->base + INTC0_SWINT_IER);
+ irq_chip_unmask_parent(data);
+}
+
+static void aspeed_swint_irq_eoi(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bit = data->hwirq - SWINT_BASE;
+
+ writel(BIT(bit), intc0->base + INTC0_SWINT_ISR);
+ irq_chip_eoi_parent(data);
+}
+
+static struct irq_chip aspeed_swint_chip = {
+ .name = "ast2700-swint",
+ .irq_eoi = aspeed_swint_irq_eoi,
+ .irq_mask = aspeed_swint_irq_mask,
+ .irq_unmask = aspeed_swint_irq_unmask,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static void aspeed_intc0_irq_mask(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK;
+ int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK;
+ unsigned int mask;
+
+ guard(raw_spinlock_irqsave)(&intc0->intc_lock);
+ mask = readl(intc0->base + INTC0_INTMX_IER + bank * 0x10) & ~BIT(bit);
+ writel(mask, intc0->base + INTC0_INTMX_IER + bank * 0x10);
+ irq_chip_mask_parent(data);
+}
+
+static void aspeed_intc0_irq_unmask(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK;
+ int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK;
+ unsigned int unmask;
+
+ guard(raw_spinlock_irqsave)(&intc0->intc_lock);
+ unmask = readl(intc0->base + INTC0_INTMX_IER + bank * 0x10) | BIT(bit);
+ writel(unmask, intc0->base + INTC0_INTMX_IER + bank * 0x10);
+ irq_chip_unmask_parent(data);
+}
+
+static void aspeed_intc0_irq_eoi(struct irq_data *data)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+ int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK;
+ int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK;
+
+ writel(BIT(bit), intc0->base + INTC0_INTMX_ISR + bank * 0x10);
+ irq_chip_eoi_parent(data);
+}
+
+static struct irq_chip aspeed_intm_chip = {
+ .name = "ast2700-intmerge",
+ .irq_eoi = aspeed_intc0_irq_eoi,
+ .irq_mask = aspeed_intc0_irq_mask,
+ .irq_unmask = aspeed_intc0_irq_unmask,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static struct irq_chip linear_intr_irq_chip = {
+ .name = "ast2700-int",
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+#define INTC0_IN_NUM 480
+#define INTC0_ROUTE_NUM 5
+
+static const aspeed_intc_output_t aspeed_intc0_routes[INTC0_IN_NUM / 32][INTC0_ROUTE_NUM] = {
+ [0] = {
+ [0b000] = 0,
+ [0b001] = 256,
+ [0b010] = 426,
+ [0b011] = AST2700_INTC_INVALID_ROUTE,
+ [0b100] = AST2700_INTC_INVALID_ROUTE,
+ },
+ [1] = {
+ [0b000] = 32,
+ [0b001] = 288,
+ [0b010] = 458,
+ [0b011] = AST2700_INTC_INVALID_ROUTE,
+ [0b100] = AST2700_INTC_INVALID_ROUTE,
+ },
+ [2] = {
+ [0b000] = 64,
+ [0b001] = 320,
+ [0b010] = 490,
+ [0b011] = AST2700_INTC_INVALID_ROUTE,
+ [0b100] = AST2700_INTC_INVALID_ROUTE,
+ },
+ [3] = {
+ [0b000] = 96,
+ [0b001] = 352,
+ [0b010] = 522,
+ [0b011] = AST2700_INTC_INVALID_ROUTE,
+ [0b100] = AST2700_INTC_INVALID_ROUTE,
+ },
+ [4] = {
+ [0b000] = 128,
+ [0b001] = 384,
+ [0b010] = 554,
+ [0b011] = 160,
+ [0b100] = 176,
+ },
+ [5] = {
+ [0b000] = 129,
+ [0b001] = 385,
+ [0b010] = 555,
+ [0b011] = 161,
+ [0b100] = 177,
+ },
+ [6] = {
+ [0b000] = 130,
+ [0b001] = 386,
+ [0b010] = 556,
+ [0b011] = 162,
+ [0b100] = 178,
+ },
+ [7] = {
+ [0b000] = 131,
+ [0b001] = 387,
+ [0b010] = 557,
+ [0b011] = 163,
+ [0b100] = 179,
+ },
+ [8] = {
+ [0b000] = 132,
+ [0b001] = 388,
+ [0b010] = 558,
+ [0b011] = 164,
+ [0b100] = 180,
+
+ },
+ [9] = {
+ [0b000] = 133,
+ [0b001] = 544,
+ [0b010] = 714,
+ [0b011] = 165,
+ [0b100] = 181,
+ },
+ [10] = {
+ [0b000] = 134,
+ [0b001] = 545,
+ [0b010] = 715,
+ [0b011] = 166,
+ [0b100] = 182,
+ },
+ [11] = {
+ [0b000] = 135,
+ [0b001] = 546,
+ [0b010] = 706,
+ [0b011] = 167,
+ [0b100] = 183,
+ },
+ [12] = {
+ [0b000] = 136,
+ [0b001] = 547,
+ [0b010] = 707,
+ [0b011] = 168,
+ [0b100] = 184,
+
+ },
+ [13] = {
+ [0b000] = 137,
+ [0b001] = 548,
+ [0b010] = 708,
+ [0b011] = 169,
+ [0b100] = 185,
+
+ },
+ [14] = {
+ [0b000] = 138,
+ [0b001] = 549,
+ [0b010] = 709,
+ [0b011] = 170,
+ [0b100] = 186,
+ },
+};
+
+#define INTC0_INTM_NUM 50
+
+static const aspeed_intc_output_t
+ aspeed_intc0_intm_routes[INTC0_INTM_NUM / 10] = {
+ [0] = 192, /* INTM00 ~ INTM09 */
+ [1] = 416, /* INTM10 ~ INTM19 */
+ [2] = 586, /* INTM20 ~ INTM29 */
+ [3] = 208, /* INTM30 ~ INTM39 */
+ [4] = 224, /* INTM40 ~ INTM49 */
+ };
+
+static bool range_contains_element(u32 start, u32 count, u32 value)
+{
+ if (WARN_ON_ONCE((U32_MAX - count) < start))
+ return false;
+
+ return value >= start && value < start + count;
+}
+
+static int
+resolve_input_from_child_ranges(const struct aspeed_intc0 *intc0,
+ const struct aspeed_intc_interrupt_range *range,
+ u32 outpin, u32 *input)
+{
+ u32 offset;
+ u32 base;
+
+ if (!range_contains_element(range->start, range->count, outpin))
+ return -ENOENT;
+
+ if (range->upstream.param_count == 0)
+ return -EINVAL;
+
+ base = range->upstream.param[0];
+ offset = outpin - range->start;
+ if ((U32_MAX - offset) < base) {
+ dev_warn(intc0->dev,
+ "%s: Arithmetic overflow for input derivation: %u + %u\n",
+ __func__, base, offset);
+ return -EINVAL;
+ }
+
+ *input = base + offset;
+ return 0;
+}
+
+static bool resolve_parent_range_for_output(const struct aspeed_intc0 *intc0,
+ const struct fwnode_handle *parent,
+ u32 output,
+ struct aspeed_intc_interrupt_range *resolved)
+{
+ for (size_t i = 0; i < intc0->ranges.nranges; i++) {
+ struct aspeed_intc_interrupt_range range =
+ intc0->ranges.ranges[i];
+
+ dev_dbg(intc0->dev,
+ "%s: Inspecting candidate parent range %zu starting at %u for %u\n",
+ __func__, i, range.start, range.count);
+ if (!range_contains_element(range.start, range.count, output)) {
+ dev_dbg(intc0->dev, "%s: Output %u not in range [%u, %u)\n",
+ __func__, output, range.start, range.start + range.count);
+ continue;
+ }
+
+ if (range.upstream.fwnode != parent) {
+ dev_dbg(intc0->dev, "%s: Parent mismatch for range %zu\n", __func__, i);
+ continue;
+ }
+
+ dev_dbg(intc0->dev, "%s: Parent range %zu matched for output %u\n",
+ __func__, i, output);
+
+ if (resolved) {
+ resolved->start = output;
+ resolved->count = 1;
+ resolved->upstream = range.upstream;
+ resolved->upstream.param[1] += output - range.start;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0,
+ const struct fwnode_handle *parent, u32 input,
+ struct aspeed_intc_interrupt_range *resolved)
+{
+ aspeed_intc_output_t c0o;
+ int rc = -ENOENT;
+
+ if (input < INT_NUM) {
+ bool found;
+
+ dev_dbg(intc0->dev, "%s: Resolving parent route for linear input %u\n",
+ __func__, input);
+ static_assert(INTC0_ROUTE_NUM < INT_MAX, "Broken cast");
+ for (size_t i = 0; rc == -ENOENT && i < INTC0_ROUTE_NUM; i++) {
+ c0o = aspeed_intc0_routes[input / 32][i];
+ if (c0o == AST2700_INTC_INVALID_ROUTE)
+ continue;
+
+ if (input < GIC_P2P_SPI_END)
+ c0o += input % 32;
+
+ found = resolve_parent_range_for_output(intc0, parent, c0o, resolved);
+ rc = found ? (int)i : -ENOENT;
+ }
+ } else if (input < (INT_NUM + INTM_NUM)) {
+ bool found;
+
+ dev_dbg(intc0->dev, "%s: Resolving parent route for merged input %u\n",
+ __func__, input);
+ c0o = aspeed_intc0_intm_routes[(input - INT_NUM) / INTM_IRQS_PER_BANK];
+ c0o += ((input - INT_NUM) % INTM_IRQS_PER_BANK);
+
+ found = resolve_parent_range_for_output(intc0, parent, c0o, resolved);
+ rc = found ? 0 : -ENOENT;
+ } else if (input < (INT_NUM + INTM_NUM + SWINT_NUM)) {
+ bool found;
+
+ dev_dbg(intc0->dev, "%s: Resolving parent route for merged input %u\n",
+ __func__, input);
+ c0o = input - SWINT_BASE + 144;
+ found = resolve_parent_range_for_output(intc0, parent, c0o, resolved);
+ rc = found ? 0 : -ENOENT;
+ } else {
+ dev_dbg(intc0->dev, "%s: Invalid input: %u\n", __func__, input);
+ return -ENOENT;
+ }
+
+ if (rc < 0) {
+ dev_dbg(intc0->dev,
+ "%s: Failed to resolve INTC0 parent route for input %u: %d\n",
+ __func__, input, rc);
+ } else {
+ dev_dbg(intc0->dev,
+ "%s: Resolved INTC0 input %u route to parent via %d\n",
+ __func__, input, rc);
+ }
+
+ return rc;
+}
+
+/**
+ * aspeed_intc0_resolve_route - Determine the necessary interrupt output at intc1
+ * @c0domain: The pointer to intc0's irq_domain
+ * @nc1outs: The number of valid intc1 outputs available for the input
+ * @c1outs: The array of available intc1 output indices for the input
+ * @nc1ranges: The number of interrupt range entries for intc1
+ * @c1ranges: The array of configured intc1 interrupt ranges
+ * @resolved: The fully resolved range entry after applying the resolution
+ * algorithm
+ *
+ * Returns: The intc1 route index associated with the intc1 output identified in
+ * @resolved on success. Otherwise, a negative errno value.
+ *
+ * The AST2700 interrupt architecture allows any peripheral interrupt source
+ * to be routed to one of up to four processors running in the SoC. A processor
+ * binding a driver for a peripheral that requests an interrupt is (without
+ * further design and effort) the destination for the requested interrupt.
+ *
+ * Routing a peripheral interrupt to its destination processor requires
+ * coordination between INTC0 on the CPU die and one or more INTC1 instances.
+ * At least one INTC1 instance exists in the SoC on the IO-die, however up
+ * to two more instances may be integrated via LTPI (LVDS Tunneling Protocol
+ * & Interface).
+ *
+ * Between the multiple destinations, various route constraints, and the
+ * devicetree binding design, some information that's needed at INTC1 instances
+ * to route inbound interrupts correctly to the destination processor is only
+ * available at INTC0.
+ *
+ * aspeed_intc0_resolve_route() is to be invoked by INTC1 driver instances to
+ * perform the route resolution. The implementation in INTC0 allows INTC0 to
+ * encapsulate the information used to perform route selection, and provides it
+ * with an opportunity to apply policy as part of the selection process. Such
+ * policy may, for instance, choose to de-prioritise some interrupts destined
+ * for the PSP (Primary Service Processor) GIC.
+ */
+int aspeed_intc0_resolve_route(const struct irq_domain *c0domain, size_t nc1outs,
+ const aspeed_intc_output_t c1outs[static nc1outs],
+ size_t nc1ranges,
+ const struct aspeed_intc_interrupt_range c1ranges[static nc1ranges],
+ struct aspeed_intc_interrupt_range *resolved)
+{
+ struct aspeed_intc0 *intc0;
+ struct fwnode_handle *parent_fwnode;
+ int ret;
+
+ if (!c0domain || !resolved)
+ return -EINVAL;
+
+ if (nc1outs > INT_MAX)
+ return -EINVAL;
+
+ if (nc1outs == 0 || nc1ranges == 0)
+ return -ENODEV;
+
+ if (!fwnode_device_is_compatible(c0domain->fwnode,
+ "aspeed,ast2700-intc0-ic"))
+ return -ENODEV;
+
+ intc0 = c0domain->host_data;
+ if (!intc0)
+ return -EINVAL;
+
+ parent_fwnode = of_fwnode_handle(intc0->parent);
+
+ for (size_t i = 0; i < nc1outs; i++) {
+ aspeed_intc_output_t c1o = c1outs[i];
+
+ if (c1o == AST2700_INTC_INVALID_ROUTE) {
+ dev_dbg(intc0->dev, "%s: Invalid output at route index %zu\n",
+ __func__, i);
+ continue;
+ }
+
+ dev_dbg(intc0->dev, "%s: Have output %u for route index %zu\n",
+ __func__, c1o, i);
+
+ for (size_t j = 0; j < nc1ranges; j++) {
+ struct aspeed_intc_interrupt_range c1r = c1ranges[j];
+ u32 input;
+
+ dev_dbg(intc0->dev,
+ "%s: Inspecting candidate range %zu starting at %u for %u\n",
+ __func__, j, c1r.start, c1r.count);
+
+ /*
+ * Range match for intc1 output pin
+ *
+ * Assume a failed match is still a match for the purpose of testing,
+ * saves a bunch of mess in the test fixtures
+ */
+ if (!(c0domain == irq_find_matching_fwspec(&c1r.upstream,
+ c0domain->bus_token) ||
+ IS_ENABLED(CONFIG_ASPEED_AST2700_INTC_TEST))) {
+ dev_dbg(intc0->dev, "%s: Parent mismatch for candidate range %zu\n",
+ __func__, j);
+ continue;
+ }
+
+ ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input);
+ if (ret) {
+ if (ret == -ENOENT)
+ dev_dbg(intc0->dev,
+ "%s: Output %u not in candidate range %zu starting at %u for %u\n",
+ __func__, c1o, j, c1r.start, c1r.count);
+ continue;
+ }
+ dev_dbg(intc0->dev,
+ "%s: Resolved INTC0 input to %u using candidate range %zu: [%u, %u)\n",
+ __func__, input, j, c1r.start, c1r.start + c1r.count);
+
+ /*
+ * INTC1 should never request routes for peripheral interrupt sources
+ * directly attached to INTC0.
+ */
+ if (input < GIC_P2P_SPI_END) {
+ dev_dbg(intc0->dev,
+ "%s: Invalid range specification at index %zu routed INTC1 output to unreachable INTC0 input\n",
+ __func__, j);
+ continue;
+ }
+
+ ret = resolve_parent_route_for_input(intc0, parent_fwnode, input, NULL);
+ if (ret < 0)
+ continue;
+
+ /* Route resolution succeeded */
+ resolved->start = c1o;
+ resolved->count = 1;
+ resolved->upstream = c1r.upstream;
+ resolved->upstream.param[0] = input;
+ dev_dbg(intc0->dev,
+ "%s: Route resolution selected INTC1 output %u via index %zu\n",
+ __func__, c1o, i);
+ /* Cast protected by prior test against nc1outs */
+ return (int)i;
+ }
+ }
+
+ ret = -EHOSTUNREACH;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aspeed_intc0_resolve_route);
+
+static int aspeed_intc0_irq_domain_map(struct irq_domain *domain,
+ unsigned int irq, irq_hw_number_t hwirq)
+{
+ if (hwirq < GIC_P2P_SPI_END)
+ irq_set_chip_and_handler(irq, &linear_intr_irq_chip,
+ handle_level_irq);
+ else if (hwirq < INTM_BASE)
+ return -EINVAL;
+ else if (hwirq < SWINT_BASE)
+ irq_set_chip_and_handler(irq, &aspeed_intm_chip,
+ handle_level_irq);
+ else if (hwirq < INT0_NUM)
+ irq_set_chip_and_handler(irq, &aspeed_swint_chip,
+ handle_level_irq);
+ else
+ return -EINVAL;
+
+ irq_set_chip_data(irq, domain->host_data);
+ return 0;
+}
+
+static int aspeed_intc0_irq_domain_translate(struct irq_domain *domain,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (fwspec->param_count != 1)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+ *type = IRQ_TYPE_NONE;
+ return 0;
+}
+
+static int aspeed_intc0_irq_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct aspeed_intc0 *intc0 = domain->host_data;
+ struct aspeed_intc_interrupt_range resolved;
+ struct irq_fwspec *fwspec = data;
+ struct irq_fwspec parent_fwspec;
+ struct irq_chip *chip;
+ unsigned long hwirq;
+ unsigned int type;
+ int ret;
+
+ ret = aspeed_intc0_irq_domain_translate(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ if (hwirq >= GIC_P2P_SPI_END && hwirq < INT_NUM)
+ return -EINVAL;
+
+ if (hwirq < INTM_BASE)
+ chip = &linear_intr_irq_chip;
+ else if (hwirq < SWINT_BASE)
+ chip = &aspeed_intm_chip;
+ else
+ chip = &aspeed_swint_chip;
+
+ ret = resolve_parent_route_for_input(intc0, domain->parent->fwnode,
+ (u32)hwirq, &resolved);
+ if (ret)
+ return ret;
+
+ parent_fwspec = resolved.upstream;
+ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+ &parent_fwspec);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < nr_irqs; ++i, ++hwirq, ++virq) {
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip,
+ domain->host_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aspeed_intc0_irq_domain_activate(struct irq_domain *domain,
+ struct irq_data *data, bool reserve)
+{
+ struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
+
+ if (data->hwirq < INT_NUM) {
+ int bank = data->hwirq / 32;
+ int bit = data->hwirq % 32;
+ u32 mask = BIT(bit);
+ int route;
+
+ route = resolve_parent_route_for_input(intc0,
+ intc0->local->parent->fwnode,
+ data->hwirq, NULL);
+ if (route < 0)
+ return route;
+
+ guard(raw_spinlock_irqsave)(&intc0->intc_lock);
+ for (int i = 0; i < 3; i++) {
+ void __iomem *sel = intc0->base + 0x200 + bank * 4 + 0x100 * i;
+ u32 reg = readl(sel);
+
+ if (route & BIT(i))
+ reg |= mask;
+ else
+ reg &= ~mask;
+
+ writel(reg, sel);
+ if (readl(sel) != reg)
+ return -EACCES;
+ }
+ } else if (data->hwirq < INT0_NUM) {
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct irq_domain_ops aspeed_intc0_ic_irq_domain_ops = {
+ .translate = aspeed_intc0_irq_domain_translate,
+ .alloc = aspeed_intc0_irq_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+ .map = aspeed_intc0_irq_domain_map,
+ .activate = aspeed_intc0_irq_domain_activate,
+};
+
+static void aspeed_intc0_disable_swint(struct aspeed_intc0 *intc0)
+{
+ writel(0, intc0->base + INTC0_SWINT_IER);
+}
+
+static void aspeed_intc0_disable_intbank(struct aspeed_intc0 *intc0)
+{
+ int i, j;
+
+ for (i = 0; i < INTC0_INTBANK_GROUPS; i++) {
+ for (j = 0; j < INTC0_INTBANKS_PER_GRP; j++) {
+ u32 base = INTC0_INTBANKX_IER + (0x100 * i) + (0x10 * j);
+
+ writel(0, intc0->base + base);
+ }
+ }
+}
+
+static void aspeed_intc0_disable_intm(struct aspeed_intc0 *intc0)
+{
+ int i;
+
+ for (i = 0; i < INTC0_INTM_BANK_NUM; i++)
+ writel(0, intc0->base + INTC0_INTMX_IER + (0x10 * i));
+}
+
+static int aspeed_intc0_ic_probe(struct platform_device *pdev,
+ struct device_node *parent)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct irq_domain *parent_domain;
+ struct aspeed_intc0 *intc0;
+ int ret;
+
+ if (!parent) {
+ pr_err("missing parent interrupt node\n");
+ return -ENODEV;
+ }
+
+ intc0 = devm_kzalloc(&pdev->dev, sizeof(*intc0), GFP_KERNEL);
+ if (!intc0)
+ return -ENOMEM;
+
+ intc0->dev = &pdev->dev;
+ intc0->parent = parent;
+ intc0->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(intc0->base))
+ return PTR_ERR(intc0->base);
+
+ aspeed_intc0_disable_swint(intc0);
+ aspeed_intc0_disable_intbank(intc0);
+ aspeed_intc0_disable_intm(intc0);
+
+ raw_spin_lock_init(&intc0->intc_lock);
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ pr_err("unable to obtain parent domain\n");
+ return -ENODEV;
+ }
+
+ if (!of_device_is_compatible(parent, "arm,gic-v3"))
+ return -ENODEV;
+
+ intc0->local = irq_domain_create_hierarchy(parent_domain, 0, INT0_NUM,
+ of_fwnode_handle(node),
+ &aspeed_intc0_ic_irq_domain_ops,
+ intc0);
+ if (!intc0->local)
+ return -ENOMEM;
+
+ ret = aspeed_intc_populate_ranges(&pdev->dev, &intc0->ranges);
+ if (ret < 0) {
+ irq_domain_remove(intc0->local);
+ return ret;
+ }
+
+ return 0;
+}
+
+IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc0)
+IRQCHIP_MATCH("aspeed,ast2700-intc0-ic", aspeed_intc0_ic_probe)
+IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc0)
+
+#ifdef CONFIG_ASPEED_AST2700_INTC_TEST
+#include "irq-ast2700-intc0-test.c"
+#endif
diff --git a/drivers/irqchip/irq-ast2700-intc1.c b/drivers/irqchip/irq-ast2700-intc1.c
new file mode 100644
index 000000000000..51371cc57c5c
--- /dev/null
+++ b/drivers/irqchip/irq-ast2700-intc1.c
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Aspeed AST2700 Interrupt Controller.
+ *
+ * Copyright (C) 2023 ASPEED Technology Inc.
+ */
+
+#include "linux/dev_printk.h"
+#include "linux/device/devres.h"
+#include "linux/property.h"
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+
+#include "irq-ast2700.h"
+
+#define INTC1_IER 0x100
+#define INTC1_ISR 0x104
+#define INTC1_IRQS_PER_BANK 32
+#define INTC1_BANK_NUM 6
+#define INTC1_ROUTE_NUM 7
+
+struct aspeed_intc1 {
+ struct device *dev;
+ void __iomem *base;
+ raw_spinlock_t intc_lock;
+ struct irq_domain *local;
+ struct irq_domain *upstream;
+ struct aspeed_intc_interrupt_ranges ranges;
+};
+
+static void aspeed_intc1_disable_int(struct aspeed_intc1 *intc1)
+{
+ for (int i = 0; i < INTC1_BANK_NUM; i++)
+ writel(0x0, intc1->base + INTC1_IER + (0x10 * i));
+}
+
+static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc)
+{
+ struct aspeed_intc1 *intc1 = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long bit, status;
+
+ chained_irq_enter(chip, desc);
+
+ for (int bank = 0; bank < INTC1_BANK_NUM; bank++) {
+ status = readl(intc1->base + INTC1_ISR + (0x10 * bank));
+ if (!status)
+ continue;
+
+ for_each_set_bit(bit, &status, INTC1_IRQS_PER_BANK) {
+ generic_handle_domain_irq(intc1->local,
+ (bank * INTC1_IRQS_PER_BANK) +
+ bit);
+ writel(BIT(bit),
+ intc1->base + INTC1_ISR + (0x10 * bank));
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void aspeed_intc1_irq_mask(struct irq_data *data)
+{
+ struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data);
+ int bank = data->hwirq / INTC1_IRQS_PER_BANK;
+ int bit = data->hwirq % INTC1_IRQS_PER_BANK;
+ unsigned int mask;
+
+ guard(raw_spinlock_irqsave)(&intc1->intc_lock);
+ mask = readl(intc1->base + INTC1_IER + (0x10 * bank)) & ~BIT(bit);
+ writel(mask, intc1->base + INTC1_IER + (0x10 * bank));
+}
+
+static void aspeed_intc1_irq_unmask(struct irq_data *data)
+{
+ struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data);
+ int bank = data->hwirq / INTC1_IRQS_PER_BANK;
+ int bit = data->hwirq % INTC1_IRQS_PER_BANK;
+ unsigned int unmask;
+
+ guard(raw_spinlock_irqsave)(&intc1->intc_lock);
+ unmask = readl(intc1->base + INTC1_IER + (0x10 * bank)) | BIT(bit);
+ writel(unmask, intc1->base + INTC1_IER + (0x10 * bank));
+}
+
+static struct irq_chip aspeed_intc_chip = {
+ .name = "ASPEED INTC1",
+ .irq_mask = aspeed_intc1_irq_mask,
+ .irq_unmask = aspeed_intc1_irq_unmask,
+};
+
+static int aspeed_intc1_irq_domain_translate(struct irq_domain *domain,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (fwspec->param_count != 1)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+ *type = IRQ_TYPE_LEVEL_HIGH;
+ return 0;
+}
+
+static int aspeed_intc1_ic_map_irq_domain(struct irq_domain *domain,
+ unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_domain_set_info(domain, irq, hwirq, &aspeed_intc_chip,
+ domain->host_data, handle_level_irq, NULL, NULL);
+ return 0;
+}
+
+#define INTC1_IN_NUM 192
+
+/*
+ * In-bound interrupts are progressively merged into one out-bound interrupt in
+ * groups of 32. Apply this fact to compress the route table in corresponding
+ * groups of 32.
+ */
+static const aspeed_intc_output_t aspeed_intc1_routes[INTC1_IN_NUM / 32][INTC1_ROUTE_NUM] = {
+ [0] = {
+ [0b000] = 0,
+ [0b001] = AST2700_INTC_INVALID_ROUTE, /* path not verified */
+ [0b010] = 10,
+ [0b011] = 20,
+ [0b100] = 30,
+ [0b101] = 40,
+ [0b110] = 50,
+ },
+ [1] = {
+ [0b000] = 1,
+ [0b001] = AST2700_INTC_INVALID_ROUTE,
+ [0b010] = 11,
+ [0b011] = 21,
+ [0b100] = 31,
+ [0b101] = 41,
+ [0b110] = 50,
+ },
+ [2] = {
+ [0b000] = 2,
+ [0b001] = AST2700_INTC_INVALID_ROUTE,
+ [0b010] = 12,
+ [0b011] = 22,
+ [0b100] = 32,
+ [0b101] = 42,
+ [0b110] = 50,
+ },
+ [3] = {
+ [0b000] = 3,
+ [0b001] = AST2700_INTC_INVALID_ROUTE,
+ [0b010] = 13,
+ [0b011] = 23,
+ [0b100] = 33,
+ [0b101] = 43,
+ [0b110] = 50,
+ },
+ [4] = {
+ [0b000] = 4,
+ [0b001] = AST2700_INTC_INVALID_ROUTE,
+ [0b010] = 14,
+ [0b011] = 24,
+ [0b100] = 34,
+ [0b101] = 44,
+ [0b110] = 50,
+ },
+ [5] = {
+ [0b000] = 5,
+ [0b001] = AST2700_INTC_INVALID_ROUTE,
+ [0b010] = 15,
+ [0b011] = 25,
+ [0b100] = 35,
+ [0b101] = 45,
+ [0b110] = 50,
+ },
+};
+
+#define INTC1_BOOTMCU_ROUTE 0b110
+
+static int aspeed_intc1_parent_is_bootmcu(const struct irq_domain *upstream)
+{
+ if (!upstream || !upstream->fwnode)
+ return 0;
+
+ return fwnode_device_is_compatible(upstream->fwnode, "riscv,aplic");
+}
+
+static int aspeed_intc1_irq_domain_activate(struct irq_domain *domain,
+ struct irq_data *data, bool reserve)
+{
+ struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data);
+ int bank = data->hwirq / INTC1_IRQS_PER_BANK;
+ struct aspeed_intc_interrupt_range resolved;
+ int bit = data->hwirq % INTC1_IRQS_PER_BANK;
+ u32 mask = BIT(bit);
+ int rc;
+
+ if (WARN_ON_ONCE((data->hwirq >> 5) >= ARRAY_SIZE(aspeed_intc1_routes)))
+ return -EINVAL;
+
+ dev_dbg(intc1->dev, "Activation request for hwirq %lu in domain %s\n",
+ data->hwirq, domain->name);
+
+ /*
+ * outpin may be an error if the upstream is the BootMCU APLIC node, or
+ * anything except a valid intc0 driver instance
+ */
+ rc = aspeed_intc0_resolve_route(intc1->upstream, INTC1_ROUTE_NUM,
+ aspeed_intc1_routes[data->hwirq >> 5],
+ intc1->ranges.nranges,
+ intc1->ranges.ranges, &resolved);
+ if (rc < 0) {
+ if (!aspeed_intc1_parent_is_bootmcu(intc1->upstream)) {
+ dev_warn(intc1->dev,
+ "Failed to resolve interrupt route for hwirq %lu in domain %s\n",
+ data->hwirq, domain->name);
+ return rc;
+ }
+ rc = INTC1_BOOTMCU_ROUTE;
+ }
+
+ guard(raw_spinlock_irqsave)(&intc1->intc_lock);
+ /* Route selector uses 3 bits across the selector registers. */
+ for (int i = 0; i < 3; i++) {
+ void __iomem *sel = intc1->base + 0x80 + bank * 4 + 0x20 * i;
+ u32 reg = readl(sel);
+
+ if (rc & BIT(i))
+ reg |= mask;
+ else
+ reg &= ~mask;
+
+ writel(reg, sel);
+ if (readl(sel) != reg)
+ return -EACCES;
+ }
+
+ dev_dbg(intc1->dev,
+ "Routed hwirq %lu in domain %s to output %u via route %d\n",
+ data->hwirq, domain->name, resolved.start, rc);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aspeed_intc1_ic_irq_domain_ops = {
+ .map = aspeed_intc1_ic_map_irq_domain,
+ .translate = aspeed_intc1_irq_domain_translate,
+ .activate = aspeed_intc1_irq_domain_activate,
+};
+
+static void aspeed_intc1_request_interrupts(struct aspeed_intc1 *intc1)
+{
+ unsigned int i;
+
+ for (i = 0; i < intc1->ranges.nranges; i++) {
+ struct aspeed_intc_interrupt_range *r =
+ &intc1->ranges.ranges[i];
+
+ if (intc1->upstream !=
+ irq_find_matching_fwspec(&r->upstream,
+ intc1->upstream->bus_token))
+ continue;
+
+ for (u32 k = 0; k < r->count; k++) {
+ struct of_phandle_args parent_irq;
+ int irq;
+
+ parent_irq.np = to_of_node(r->upstream.fwnode);
+ parent_irq.args_count = 1;
+ parent_irq.args[0] =
+ intc1->ranges.ranges[i].upstream.param[0] + k;
+
+ irq = irq_create_of_mapping(&parent_irq);
+ if (!irq)
+ continue;
+
+ irq_set_chained_handler_and_data(irq,
+ aspeed_intc1_ic_irq_handler, intc1);
+ dev_dbg(intc1->dev, "Mapped irq %d\n", parent_irq.args[0]);
+ }
+ }
+}
+
+static int aspeed_intc1_ic_probe(struct platform_device *pdev,
+ struct device_node *parent)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct aspeed_intc1 *intc1;
+ struct irq_domain *host;
+ int ret;
+
+ if (!parent) {
+ dev_err(&pdev->dev, "missing parent interrupt node\n");
+ return -ENODEV;
+ }
+
+ if (!of_device_is_compatible(parent, "aspeed,ast2700-intc0-ic"))
+ return -ENODEV;
+
+ host = irq_find_host(parent);
+ if (!host)
+ return -ENODEV;
+
+ intc1 = devm_kzalloc(&pdev->dev, sizeof(*intc1), GFP_KERNEL);
+ if (!intc1)
+ return -ENOMEM;
+
+ intc1->dev = &pdev->dev;
+ intc1->upstream = host;
+ intc1->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(intc1->base))
+ return PTR_ERR(intc1->base);
+
+ aspeed_intc1_disable_int(intc1);
+
+ raw_spin_lock_init(&intc1->intc_lock);
+
+ intc1->local = irq_domain_create_linear(of_fwnode_handle(node),
+ INTC1_BANK_NUM * INTC1_IRQS_PER_BANK,
+ &aspeed_intc1_ic_irq_domain_ops, intc1);
+ if (!intc1->local)
+ return -ENOMEM;
+
+ ret = aspeed_intc_populate_ranges(&pdev->dev, &intc1->ranges);
+ if (ret < 0) {
+ irq_domain_remove(intc1->local);
+ return ret;
+ }
+
+ aspeed_intc1_request_interrupts(intc1);
+
+ return 0;
+}
+
+IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc1)
+IRQCHIP_MATCH("aspeed,ast2700-intc1-ic", aspeed_intc1_ic_probe)
+IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc1)
diff --git a/drivers/irqchip/irq-ast2700.c b/drivers/irqchip/irq-ast2700.c
new file mode 100644
index 000000000000..269d743207ae
--- /dev/null
+++ b/drivers/irqchip/irq-ast2700.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Aspeed Interrupt Controller.
+ *
+ * Copyright (C) 2023 ASPEED Technology Inc.
+ */
+#include "irq-ast2700.h"
+
+#include <linux/dev_printk.h>
+#include <linux/device/devres.h>
+
+int aspeed_intc_populate_ranges(struct device *dev,
+ struct aspeed_intc_interrupt_ranges *ranges)
+{
+ struct aspeed_intc_interrupt_range *arr;
+ const __be32 *pvs, *pve;
+ struct device_node *dn;
+ int len;
+
+ if (!dev || !ranges)
+ return -EINVAL;
+
+ dn = dev->of_node;
+
+ pvs = of_get_property(dn, "aspeed,interrupt-ranges", &len);
+ if (!pvs)
+ return -EINVAL;
+
+ if (len % sizeof(__be32))
+ return -EINVAL;
+
+ /* Over-estimate the range entry count for now */
+ ranges->ranges = devm_kmalloc_array(dev, (len / (3 * sizeof(__be32))),
+ sizeof(*ranges->ranges),
+ GFP_KERNEL);
+ if (!ranges->ranges)
+ return -ENOMEM;
+
+ pve = pvs + (len / sizeof(__be32));
+ for (unsigned int i = 0; pve - pvs >= 3; i++) {
+ struct aspeed_intc_interrupt_range *r;
+ struct device_node *target;
+ u32 target_cells;
+
+ target = of_find_node_by_phandle(be32_to_cpu(pvs[2]));
+ if (!target)
+ return -EINVAL;
+
+ if (of_property_read_u32(target, "#interrupt-cells",
+ &target_cells)) {
+ of_node_put(target);
+ return -EINVAL;
+ }
+
+ if (!target_cells || target_cells > IRQ_DOMAIN_IRQ_SPEC_PARAMS) {
+ of_node_put(target);
+ return -EINVAL;
+ }
+
+ if (pve - pvs < 3 + target_cells) {
+ of_node_put(target);
+ return -EINVAL;
+ }
+
+ r = &ranges->ranges[i];
+ r->start = be32_to_cpu(pvs[0]);
+ r->count = be32_to_cpu(pvs[1]);
+
+ {
+ struct of_phandle_args args = {
+ .np = target,
+ .args_count = target_cells,
+ };
+
+ for (u32 j = 0; j < target_cells; j++)
+ args.args[j] = be32_to_cpu(pvs[3 + j]);
+
+ of_phandle_args_to_fwspec(target, args.args,
+ args.args_count,
+ &r->upstream);
+ }
+
+ if (target_cells >= 1)
+ dev_dbg(dev,
+ "Mapped %u outputs from %u to %u on parent %s",
+ r->count, r->start, r->upstream.param[0], target->full_name);
+ else
+ dev_dbg(dev,
+ "Registered interrupt range from %u for count %u\n",
+ r->start, r->count);
+
+ of_node_put(target);
+ pvs += 3 + target_cells;
+ ranges->nranges++;
+ }
+
+ /* Re-fit the range array now we know the entry count */
+ arr = devm_krealloc_array(dev, ranges->ranges, ranges->nranges,
+ sizeof(*ranges->ranges), GFP_KERNEL);
+ if (!arr)
+ return -ENOMEM;
+ ranges->ranges = arr;
+
+ return 0;
+}
diff --git a/drivers/irqchip/irq-ast2700.h b/drivers/irqchip/irq-ast2700.h
new file mode 100644
index 000000000000..56dbb1c88b11
--- /dev/null
+++ b/drivers/irqchip/irq-ast2700.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Aspeed AST2700 Interrupt Controller.
+ *
+ * Copyright (C) 2023 ASPEED Technology Inc.
+ */
+#ifndef DRIVERS_IRQCHIP_AST2700
+#define DRIVERS_IRQCHIP_AST2700
+
+#include <linux/device.h>
+#include <linux/irqdomain.h>
+
+#define AST2700_INTC_INVALID_ROUTE (~0U)
+
+struct aspeed_intc_interrupt_range {
+ u32 start;
+ u32 count;
+ struct irq_fwspec upstream;
+};
+
+struct aspeed_intc_interrupt_ranges {
+ struct aspeed_intc_interrupt_range *ranges;
+ unsigned int nranges;
+};
+
+int aspeed_intc_populate_ranges(struct device *dev,
+ struct aspeed_intc_interrupt_ranges *ranges);
+
+typedef u32 aspeed_intc_output_t;
+
+int aspeed_intc0_resolve_route(
+ const struct irq_domain *c0domain, size_t nc1outs,
+ const aspeed_intc_output_t c1outs[static nc1outs], size_t nc1ranges,
+ const struct aspeed_intc_interrupt_range c1ranges[static nc1ranges],
+ struct aspeed_intc_interrupt_range *resolved);
+
+#endif
--
2.34.1
On Thu, Feb 05 2026 at 14:07, Ryan Chen wrote:
> @@ -88,6 +88,7 @@ obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
> obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o
> obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o
> obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
> +obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o irq-ast2700-intc0.o irq-ast2700-intc1.o
> obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o
> obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o
> obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o
> diff --git a/drivers/irqchip/irq-ast2700-intc0-test.c b/drivers/irqchip/irq-ast2700-intc0-test.c
How is this kunit test supposed to be built?
Also split this kunit thing out into a separate patch. It is not
relevant for the functional part.
> new file mode 100644
> index 000000000000..d6bc19676b2e
> --- /dev/null
> +++ b/drivers/irqchip/irq-ast2700-intc0-test.c
> @@ -0,0 +1,474 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Code Construct
> + */
> +#include <kunit/test.h>
> +#include "irq-ast2700.h"
> +
> +static void aspeed_intc0_resolve_route_bad_args(struct kunit *test)
> +{
> + static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 };
> + static const aspeed_intc_output_t c1outs[] = { 0 };
> + struct aspeed_intc_interrupt_range resolved;
> + const struct irq_domain c0domain = { 0 };
> +
Pointless newline
> + int rc;
> +
> + rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL);
> + KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> + rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs,
> + ARRAY_SIZE(c1ranges), c1ranges,
> + &resolved);
> + KUNIT_EXPECT_EQ(test, rc, -ENODEV);
> +
> + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
> + 0, c1ranges, &resolved);
> + KUNIT_EXPECT_EQ(test, rc, -ENODEV);
> +}
> +
> +static int
> +arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle,
> + const char *propname, const char **val,
> + size_t nval)
Please use the full 100 character you have available and avoid extra
line breaks. It fits nicely into two lines:
static int arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle,
const char *propname, const char **val, size_t nval)
There is also no real point to have these overly long function and
argument names.
> +#include <asm-generic/errno.h>
That's wrong. Include <linux/errno.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +#include "irq-ast2700.h"
Missing newline
> +#define INT_NUM 480
> +#define INTM_NUM 50
> +#define SWINT_NUM 16
> +
> +#define INTM_BASE (INT_NUM)
> +#define SWINT_BASE (INT_NUM + INTM_NUM)
> +#define INT0_NUM (INT_NUM + INTM_NUM + SWINT_NUM)
> +
> +#define GIC_P2P_SPI_END 128
> +
> +#define INTC0_SWINT_IER 0x10
> +#define INTC0_SWINT_ISR 0x14
> +#define INTC0_INTBANKX_IER 0x1000
> +#define INTC0_INTBANK_GROUPS 11
> +#define INTC0_INTBANKS_PER_GRP 3
> +#define INTC0_INTMX_IER 0x1b00
> +#define INTC0_INTMX_ISR 0x1b04
> +#define INTC0_INTM_BANK_NUM 3
> +#define INTM_IRQS_PER_BANK 10
If you make these defines tabular and they become readable:
#define INT_NUM 480
#define INTM_NUM 50
...
#define INTM_BASE (INT_NUM)
...
#define GIC_P2P_SPI_END 128
...
#define INTC0_SWINT_IER 0x10
See?
> +struct aspeed_intc0 {
> + struct device *dev;
> + void __iomem *base;
> + raw_spinlock_t intc_lock;
> + struct irq_domain *local;
> + struct device_node *parent;
> + struct aspeed_intc_interrupt_ranges ranges;
> +};
https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-declarations-and-initializers
I pointed you to that documentation before. Do I really have to remind
you every couple of week?
> +
> +static void aspeed_swint_irq_mask(struct irq_data *data)
> +{
> + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
> + int bit = data->hwirq - SWINT_BASE;
> + unsigned int mask;
> +
> + guard(raw_spinlock_irqsave)(&intc0->intc_lock);
s/_irqsave// Interrupts are disabled when this is invoked.
> + mask = readl(intc0->base + INTC0_SWINT_IER) & ~BIT(bit);
> + writel(mask, intc0->base + INTC0_SWINT_IER);
> + irq_chip_mask_parent(data);
> +}
> +
> +static void aspeed_swint_irq_unmask(struct irq_data *data)
> +{
> + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
> + int bit = data->hwirq - SWINT_BASE;
> + unsigned int unmask;
> +
> + guard(raw_spinlock_irqsave)(&intc0->intc_lock);
> + unmask = readl(intc0->base + INTC0_SWINT_IER) | BIT(bit);
These unmask/mask variable are simply not helpful. What's wrong with
naming them 'ier' because that's what this is about. And while at it the
data type for hardware related variables is u32 not unsigned int to make
it clear.
> +static struct irq_chip aspeed_swint_chip = {
> + .name = "ast2700-swint",
> + .irq_eoi = aspeed_swint_irq_eoi,
> + .irq_mask = aspeed_swint_irq_mask,
> + .irq_unmask = aspeed_swint_irq_unmask,
> + .irq_set_affinity = irq_chip_set_affinity_parent,
> + .flags = IRQCHIP_SET_TYPE_MASKED,
See above
> +
> +#define INTC0_IN_NUM 480
> +#define INTC0_ROUTE_NUM 5
Those should be at the top of the file next to the other constants.
> +static const aspeed_intc_output_t aspeed_intc0_routes[INTC0_IN_NUM / 32][INTC0_ROUTE_NUM] = {
> + [0] = {
> + [0b000] = 0,
> + [0b001] = 256,
> + [0b010] = 426,
> + [0b011] = AST2700_INTC_INVALID_ROUTE,
> + [0b100] = AST2700_INTC_INVALID_ROUTE,
Seriously? What's the point of this binary notation and the insane
amount of space this table occupies?
[0] = { 0, 256, 426, AST2700_INTC_INVALID_ROUTE, AST2700_INTC_INVALID_ROUTE },
[1] = { 32, 288, 458, AST2700_INTC_INVALID_ROUTE, AST2700_INTC_INVALID_ROUTE },
[4] = { 128, 384, 554, 160, 176 },
...
> +
> +#define INTC0_INTM_NUM 50
> +
> +static const aspeed_intc_output_t
> + aspeed_intc0_intm_routes[INTC0_INTM_NUM / 10] = {
pointless line break
> + [0] = 192, /* INTM00 ~ INTM09 */
> + [1] = 416, /* INTM10 ~ INTM19 */
> + [2] = 586, /* INTM20 ~ INTM29 */
> + [3] = 208, /* INTM30 ~ INTM39 */
> + [4] = 224, /* INTM40 ~ INTM49 */
> + };
> +
> +static bool range_contains_element(u32 start, u32 count, u32 value)
in_range32() provides that already
> +{
> + if (WARN_ON_ONCE((U32_MAX - count) < start))
> + return false;
> +
> + return value >= start && value < start + count;
> +}
> +
> +static int
> +resolve_input_from_child_ranges(const struct aspeed_intc0 *intc0,
> + const struct aspeed_intc_interrupt_range *range,
> + u32 outpin, u32 *input)
> +{
> + u32 offset;
> + u32 base;
One line
> +
> + if (!range_contains_element(range->start, range->count, outpin))
> + return -ENOENT;
> +
> + if (range->upstream.param_count == 0)
> + return -EINVAL;
> +
> + base = range->upstream.param[0];
> + offset = outpin - range->start;
> + if ((U32_MAX - offset) < base) {
if (!in_range32(...)
> + dev_warn(intc0->dev,
> + "%s: Arithmetic overflow for input derivation: %u + %u\n",
Pointless line break. Please fix them all over the place.
> + __func__, base, offset);
> + return -EINVAL;
> + }
> +
> + *input = base + offset;
> + return 0;
> +static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0,
> + const struct fwnode_handle *parent, u32 input,
> + struct aspeed_intc_interrupt_range *resolved)
> +{
> + aspeed_intc_output_t c0o;
> + int rc = -ENOENT;
> +
> + if (input < INT_NUM) {
> + bool found;
> +
> + dev_dbg(intc0->dev, "%s: Resolving parent route for linear input %u\n",
> + __func__, input);
Do you really still need all those debug prints or are you trusting your
code by now?
If they still are considered valuable then shorten them in a sensible
way so they nicely hide in the code instead of cluttering it to the
point of making it unreadable.
> +{
> + struct aspeed_intc0 *intc0;
> + struct fwnode_handle *parent_fwnode;
> + int ret;
See Documentation about variable declarations...
> + for (size_t i = 0; i < nc1outs; i++) {
> + aspeed_intc_output_t c1o = c1outs[i];
> +
> + if (c1o == AST2700_INTC_INVALID_ROUTE) {
> + dev_dbg(intc0->dev, "%s: Invalid output at route index %zu\n",
> + __func__, i);
> + continue;
> + }
> +
> + dev_dbg(intc0->dev, "%s: Have output %u for route index %zu\n",
> + __func__, c1o, i);
> +
> + for (size_t j = 0; j < nc1ranges; j++) {
> + struct aspeed_intc_interrupt_range c1r = c1ranges[j];
> + u32 input;
> +
> + dev_dbg(intc0->dev,
> + "%s: Inspecting candidate range %zu starting at %u for %u\n",
> + __func__, j, c1r.start, c1r.count);
> +
> + /*
> + * Range match for intc1 output pin
> + *
> + * Assume a failed match is still a match for the purpose of testing,
> + * saves a bunch of mess in the test fixtures
> + */
> + if (!(c0domain == irq_find_matching_fwspec(&c1r.upstream,
> + c0domain->bus_token) ||
> + IS_ENABLED(CONFIG_ASPEED_AST2700_INTC_TEST))) {
> + dev_dbg(intc0->dev, "%s: Parent mismatch for candidate range %zu\n",
> + __func__, j);
> + continue;
> + }
> +
> + ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input);
> + if (ret) {
> + if (ret == -ENOENT)
> + dev_dbg(intc0->dev,
> + "%s: Output %u not in candidate range %zu starting at %u for %u\n",
> + __func__, c1o, j, c1r.start, c1r.count);
> + continue;
All of this is unreadable and I told you about the bracket rules before, no?
> + }
> + dev_dbg(intc0->dev,
> + "%s: Resolved INTC0 input to %u using candidate range %zu: [%u, %u)\n",
> + __func__, input, j, c1r.start, c1r.start + c1r.count);
> +
> + /*
> + * INTC1 should never request routes for peripheral interrupt sources
> + * directly attached to INTC0.
> + */
> + if (input < GIC_P2P_SPI_END) {
> + dev_dbg(intc0->dev,
> + "%s: Invalid range specification at index %zu routed INTC1 output to unreachable INTC0 input\n",
> + __func__, j);
> + continue;
> + }
> +
> + ret = resolve_parent_route_for_input(intc0, parent_fwnode, input, NULL);
> + if (ret < 0)
> + continue;
> +
> + /* Route resolution succeeded */
> + resolved->start = c1o;
> + resolved->count = 1;
> + resolved->upstream = c1r.upstream;
> + resolved->upstream.param[0] = input;
> + dev_dbg(intc0->dev,
> + "%s: Route resolution selected INTC1 output %u via index %zu\n",
> + __func__, c1o, i);
> + /* Cast protected by prior test against nc1outs */
> + return (int)i;
> + }
> + }
> +
> + ret = -EHOSTUNREACH;
> + return ret;
Impressive.
> +}
> +EXPORT_SYMBOL_GPL(aspeed_intc0_resolve_route);
What is this export for? All usage sites are built in, no?
> +static int aspeed_intc0_irq_domain_map(struct irq_domain *domain,
> + unsigned int irq, irq_hw_number_t hwirq)
> +{
> + if (hwirq < GIC_P2P_SPI_END)
> + irq_set_chip_and_handler(irq, &linear_intr_irq_chip,
> + handle_level_irq);
Make this one line. Otherwise you need brackets.
> + else if (hwirq < INTM_BASE)
> + return -EINVAL;
> + else if (hwirq < SWINT_BASE)
> + irq_set_chip_and_handler(irq, &aspeed_intm_chip,
> + handle_level_irq);
> + else if (hwirq < INT0_NUM)
> + irq_set_chip_and_handler(irq, &aspeed_swint_chip,
> + handle_level_irq);
> + else
> + return -EINVAL;
> +
> + irq_set_chip_data(irq, domain->host_data);
> + return 0;
> +}
> +static int aspeed_intc0_irq_domain_activate(struct irq_domain *domain,
> + struct irq_data *data, bool reserve)
> +{
> + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data);
> +
> + if (data->hwirq < INT_NUM) {
> + int bank = data->hwirq / 32;
> + int bit = data->hwirq % 32;
> + u32 mask = BIT(bit);
> + int route;
> +
> + route = resolve_parent_route_for_input(intc0,
> + intc0->local->parent->fwnode,
> + data->hwirq, NULL);
> + if (route < 0)
> + return route;
> +
> + guard(raw_spinlock_irqsave)(&intc0->intc_lock);
> + for (int i = 0; i < 3; i++) {
> + void __iomem *sel = intc0->base + 0x200 + bank * 4 + 0x100 * i;
Magic constants 0x200 4 and 0x100. Use proper defines and a macro/inline
to calculate the register address and not this incomprehensible garbage.
> + u32 reg = readl(sel);
> +
> + if (route & BIT(i))
> + reg |= mask;
> + else
> + reg &= ~mask;
> +
> + writel(reg, sel);
> + if (readl(sel) != reg)
> + return -EACCES;
> + }
> + } else if (data->hwirq < INT0_NUM) {
> + return 0;
> + } else {
> + return -EINVAL;
> + }
If you rearrange those conditions you can avoid the indentation all
together
if (in_range32(data->hwirq, INTM_BASE, INTM_NUM + SWINT_NUM))
return 0;
if (data->hwirq >= INT_NUM)
return -EINVAL;
No?
> +
> + return 0;
> +}
> +
> +static void aspeed_intc0_disable_intbank(struct aspeed_intc0 *intc0)
> +{
> + int i, j;
> +
> + for (i = 0; i < INTC0_INTBANK_GROUPS; i++) {
> + for (j = 0; j < INTC0_INTBANKS_PER_GRP; j++) {
Both i and j should be declared in the for () statement. Your coding
style is so inconsistent it's not even funny anymore.
> + u32 base = INTC0_INTBANKX_IER + (0x100 * i) + (0x10 * j);
> +
> + writel(0, intc0->base + base);
> + }
> + }
> +}
> +IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc0)
> +IRQCHIP_MATCH("aspeed,ast2700-intc0-ic", aspeed_intc0_ic_probe)
> +IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc0)
> +
> +#ifdef CONFIG_ASPEED_AST2700_INTC_TEST
> +#include "irq-ast2700-intc0-test.c"
> +#endif
Yikes. What's wrong with Makefile?
> diff --git a/drivers/irqchip/irq-ast2700-intc1.c b/drivers/irqchip/irq-ast2700-intc1.c
> +static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc)
> +{
> + struct aspeed_intc1 *intc1 = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + unsigned long bit, status;
> +
> + chained_irq_enter(chip, desc);
> +
> + for (int bank = 0; bank < INTC1_BANK_NUM; bank++) {
> + status = readl(intc1->base + INTC1_ISR + (0x10 * bank));
> + if (!status)
> + continue;
> +
> + for_each_set_bit(bit, &status, INTC1_IRQS_PER_BANK) {
> + generic_handle_domain_irq(intc1->local,
> + (bank * INTC1_IRQS_PER_BANK) +
> + bit);
> + writel(BIT(bit),
> + intc1->base + INTC1_ISR + (0x10 * bank));
My eyes bleed by now.
Thanks,
tglx
Hi Ryan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8]
url: https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-interrupt-controller-aspeed-Add-ASPEED-AST2700-INTC0-INTC1/20260205-141046
base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
patch link: https://lore.kernel.org/r/20260205-irqchip-v1-2-b0310e06c087%40aspeedtech.com
patch subject: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support
config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20260205/202602052233.HNk5pa4R-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602052233.HNk5pa4R-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/202602052233.HNk5pa4R-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from arch/mips/include/asm/errno.h:11,
from include/linux/err.h:8,
from include/linux/cleanup.h:6,
from include/linux/jump_label.h:78,
from include/linux/dynamic_debug.h:6,
from include/linux/printk.h:621,
from include/asm-generic/bug.h:31,
from arch/mips/include/asm/bug.h:42,
from include/linux/bug.h:5,
from include/linux/thread_info.h:13,
from include/asm-generic/current.h:6,
from ./arch/mips/include/generated/asm/current.h:1,
from include/linux/sched.h:12,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from drivers/irqchip/irq-ast2700-intc0.c:10:
>> arch/mips/include/uapi/asm/errno.h:18:9: warning: 'ENOMSG' redefined
18 | #define ENOMSG 35 /* No message of desired type */
| ^~~~~~
In file included from drivers/irqchip/irq-ast2700-intc0.c:8:
include/uapi/asm-generic/errno.h:23:9: note: this is the location of the previous definition
23 | #define ENOMSG 42 /* No message of desired type */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:19:9: warning: 'EIDRM' redefined
19 | #define EIDRM 36 /* Identifier removed */
| ^~~~~
include/uapi/asm-generic/errno.h:24:9: note: this is the location of the previous definition
24 | #define EIDRM 43 /* Identifier removed */
| ^~~~~
>> arch/mips/include/uapi/asm/errno.h:20:9: warning: 'ECHRNG' redefined
20 | #define ECHRNG 37 /* Channel number out of range */
| ^~~~~~
include/uapi/asm-generic/errno.h:25:9: note: this is the location of the previous definition
25 | #define ECHRNG 44 /* Channel number out of range */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:21:9: warning: 'EL2NSYNC' redefined
21 | #define EL2NSYNC 38 /* Level 2 not synchronized */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:26:9: note: this is the location of the previous definition
26 | #define EL2NSYNC 45 /* Level 2 not synchronized */
| ^~~~~~~~
>> arch/mips/include/uapi/asm/errno.h:22:9: warning: 'EL3HLT' redefined
22 | #define EL3HLT 39 /* Level 3 halted */
| ^~~~~~
include/uapi/asm-generic/errno.h:27:9: note: this is the location of the previous definition
27 | #define EL3HLT 46 /* Level 3 halted */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:23:9: warning: 'EL3RST' redefined
23 | #define EL3RST 40 /* Level 3 reset */
| ^~~~~~
include/uapi/asm-generic/errno.h:28:9: note: this is the location of the previous definition
28 | #define EL3RST 47 /* Level 3 reset */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:24:9: warning: 'ELNRNG' redefined
24 | #define ELNRNG 41 /* Link number out of range */
| ^~~~~~
include/uapi/asm-generic/errno.h:29:9: note: this is the location of the previous definition
29 | #define ELNRNG 48 /* Link number out of range */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:25:9: warning: 'EUNATCH' redefined
25 | #define EUNATCH 42 /* Protocol driver not attached */
| ^~~~~~~
include/uapi/asm-generic/errno.h:30:9: note: this is the location of the previous definition
30 | #define EUNATCH 49 /* Protocol driver not attached */
| ^~~~~~~
>> arch/mips/include/uapi/asm/errno.h:26:9: warning: 'ENOCSI' redefined
26 | #define ENOCSI 43 /* No CSI structure available */
| ^~~~~~
include/uapi/asm-generic/errno.h:31:9: note: this is the location of the previous definition
31 | #define ENOCSI 50 /* No CSI structure available */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:27:9: warning: 'EL2HLT' redefined
27 | #define EL2HLT 44 /* Level 2 halted */
| ^~~~~~
include/uapi/asm-generic/errno.h:32:9: note: this is the location of the previous definition
32 | #define EL2HLT 51 /* Level 2 halted */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:28:9: warning: 'EDEADLK' redefined
28 | #define EDEADLK 45 /* Resource deadlock would occur */
| ^~~~~~~
include/uapi/asm-generic/errno.h:7:9: note: this is the location of the previous definition
7 | #define EDEADLK 35 /* Resource deadlock would occur */
| ^~~~~~~
>> arch/mips/include/uapi/asm/errno.h:29:9: warning: 'ENOLCK' redefined
29 | #define ENOLCK 46 /* No record locks available */
| ^~~~~~
include/uapi/asm-generic/errno.h:9:9: note: this is the location of the previous definition
9 | #define ENOLCK 37 /* No record locks available */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:30:9: warning: 'EBADE' redefined
30 | #define EBADE 50 /* Invalid exchange */
| ^~~~~
include/uapi/asm-generic/errno.h:33:9: note: this is the location of the previous definition
33 | #define EBADE 52 /* Invalid exchange */
| ^~~~~
>> arch/mips/include/uapi/asm/errno.h:31:9: warning: 'EBADR' redefined
31 | #define EBADR 51 /* Invalid request descriptor */
| ^~~~~
include/uapi/asm-generic/errno.h:34:9: note: this is the location of the previous definition
34 | #define EBADR 53 /* Invalid request descriptor */
| ^~~~~
>> arch/mips/include/uapi/asm/errno.h:32:9: warning: 'EXFULL' redefined
32 | #define EXFULL 52 /* Exchange full */
| ^~~~~~
include/uapi/asm-generic/errno.h:35:9: note: this is the location of the previous definition
35 | #define EXFULL 54 /* Exchange full */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:33:9: warning: 'ENOANO' redefined
33 | #define ENOANO 53 /* No anode */
| ^~~~~~
include/uapi/asm-generic/errno.h:36:9: note: this is the location of the previous definition
36 | #define ENOANO 55 /* No anode */
| ^~~~~~
>> arch/mips/include/uapi/asm/errno.h:34:9: warning: 'EBADRQC' redefined
34 | #define EBADRQC 54 /* Invalid request code */
| ^~~~~~~
include/uapi/asm-generic/errno.h:37:9: note: this is the location of the previous definition
37 | #define EBADRQC 56 /* Invalid request code */
| ^~~~~~~
>> arch/mips/include/uapi/asm/errno.h:35:9: warning: 'EBADSLT' redefined
35 | #define EBADSLT 55 /* Invalid slot */
| ^~~~~~~
include/uapi/asm-generic/errno.h:38:9: note: this is the location of the previous definition
38 | #define EBADSLT 57 /* Invalid slot */
| ^~~~~~~
>> arch/mips/include/uapi/asm/errno.h:36:9: warning: 'EDEADLOCK' redefined
36 | #define EDEADLOCK 56 /* File locking deadlock error */
| ^~~~~~~~~
include/uapi/asm-generic/errno.h:40:9: note: this is the location of the previous definition
40 | #define EDEADLOCK EDEADLK
| ^~~~~~~~~
>> arch/mips/include/uapi/asm/errno.h:51:9: warning: 'EMULTIHOP' redefined
51 | #define EMULTIHOP 74 /* Multihop attempted */
| ^~~~~~~~~
include/uapi/asm-generic/errno.h:55:9: note: this is the location of the previous definition
55 | #define EMULTIHOP 72 /* Multihop attempted */
| ^~~~~~~~~
arch/mips/include/uapi/asm/errno.h:52:9: warning: 'EBADMSG' redefined
52 | #define EBADMSG 77 /* Not a data message */
| ^~~~~~~
include/uapi/asm-generic/errno.h:57:9: note: this is the location of the previous definition
57 | #define EBADMSG 74 /* Not a data message */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:53:9: warning: 'ENAMETOOLONG' redefined
53 | #define ENAMETOOLONG 78 /* File name too long */
| ^~~~~~~~~~~~
include/uapi/asm-generic/errno.h:8:9: note: this is the location of the previous definition
8 | #define ENAMETOOLONG 36 /* File name too long */
| ^~~~~~~~~~~~
arch/mips/include/uapi/asm/errno.h:54:9: warning: 'EOVERFLOW' redefined
54 | #define EOVERFLOW 79 /* Value too large for defined data type */
| ^~~~~~~~~
include/uapi/asm-generic/errno.h:58:9: note: this is the location of the previous definition
58 | #define EOVERFLOW 75 /* Value too large for defined data type */
| ^~~~~~~~~
arch/mips/include/uapi/asm/errno.h:55:9: warning: 'ENOTUNIQ' redefined
55 | #define ENOTUNIQ 80 /* Name not unique on network */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:59:9: note: this is the location of the previous definition
59 | #define ENOTUNIQ 76 /* Name not unique on network */
| ^~~~~~~~
arch/mips/include/uapi/asm/errno.h:56:9: warning: 'EBADFD' redefined
56 | #define EBADFD 81 /* File descriptor in bad state */
| ^~~~~~
include/uapi/asm-generic/errno.h:60:9: note: this is the location of the previous definition
60 | #define EBADFD 77 /* File descriptor in bad state */
| ^~~~~~
arch/mips/include/uapi/asm/errno.h:57:9: warning: 'EREMCHG' redefined
57 | #define EREMCHG 82 /* Remote address changed */
| ^~~~~~~
include/uapi/asm-generic/errno.h:61:9: note: this is the location of the previous definition
61 | #define EREMCHG 78 /* Remote address changed */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:58:9: warning: 'ELIBACC' redefined
58 | #define ELIBACC 83 /* Can not access a needed shared library */
| ^~~~~~~
include/uapi/asm-generic/errno.h:62:9: note: this is the location of the previous definition
62 | #define ELIBACC 79 /* Can not access a needed shared library */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:59:9: warning: 'ELIBBAD' redefined
59 | #define ELIBBAD 84 /* Accessing a corrupted shared library */
| ^~~~~~~
include/uapi/asm-generic/errno.h:63:9: note: this is the location of the previous definition
63 | #define ELIBBAD 80 /* Accessing a corrupted shared library */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:60:9: warning: 'ELIBSCN' redefined
60 | #define ELIBSCN 85 /* .lib section in a.out corrupted */
| ^~~~~~~
include/uapi/asm-generic/errno.h:64:9: note: this is the location of the previous definition
64 | #define ELIBSCN 81 /* .lib section in a.out corrupted */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:61:9: warning: 'ELIBMAX' redefined
61 | #define ELIBMAX 86 /* Attempting to link in too many shared libraries */
| ^~~~~~~
include/uapi/asm-generic/errno.h:65:9: note: this is the location of the previous definition
65 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */
| ^~~~~~~
arch/mips/include/uapi/asm/errno.h:62:9: warning: 'ELIBEXEC' redefined
62 | #define ELIBEXEC 87 /* Cannot exec a shared library directly */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:66:9: note: this is the location of the previous definition
66 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */
| ^~~~~~~~
arch/mips/include/uapi/asm/errno.h:63:9: warning: 'EILSEQ' redefined
63 | #define EILSEQ 88 /* Illegal byte sequence */
| ^~~~~~
include/uapi/asm-generic/errno.h:67:9: note: this is the location of the previous definition
67 | #define EILSEQ 84 /* Illegal byte sequence */
| ^~~~~~
arch/mips/include/uapi/asm/errno.h:64:9: warning: 'ENOSYS' redefined
64 | #define ENOSYS 89 /* Function not implemented */
| ^~~~~~
include/uapi/asm-generic/errno.h:18:9: note: this is the location of the previous definition
18 | #define ENOSYS 38 /* Invalid system call number */
| ^~~~~~
arch/mips/include/uapi/asm/errno.h:65:9: warning: 'ELOOP' redefined
65 | #define ELOOP 90 /* Too many symbolic links encountered */
| ^~~~~
include/uapi/asm-generic/errno.h:21:9: note: this is the location of the previous definition
21 | #define ELOOP 40 /* Too many symbolic links encountered */
| ^~~~~
arch/mips/include/uapi/asm/errno.h:66:9: warning: 'ERESTART' redefined
66 | #define ERESTART 91 /* Interrupted system call should be restarted */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:68:9: note: this is the location of the previous definition
68 | #define ERESTART 85 /* Interrupted system call should be restarted */
| ^~~~~~~~
arch/mips/include/uapi/asm/errno.h:67:9: warning: 'ESTRPIPE' redefined
67 | #define ESTRPIPE 92 /* Streams pipe error */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:69:9: note: this is the location of the previous definition
69 | #define ESTRPIPE 86 /* Streams pipe error */
vim +/ENOMSG +18 arch/mips/include/uapi/asm/errno.h
61730c538f8281 David Howells 2012-10-09 17
61730c538f8281 David Howells 2012-10-09 @18 #define ENOMSG 35 /* No message of desired type */
61730c538f8281 David Howells 2012-10-09 @19 #define EIDRM 36 /* Identifier removed */
61730c538f8281 David Howells 2012-10-09 @20 #define ECHRNG 37 /* Channel number out of range */
61730c538f8281 David Howells 2012-10-09 @21 #define EL2NSYNC 38 /* Level 2 not synchronized */
61730c538f8281 David Howells 2012-10-09 @22 #define EL3HLT 39 /* Level 3 halted */
61730c538f8281 David Howells 2012-10-09 @23 #define EL3RST 40 /* Level 3 reset */
61730c538f8281 David Howells 2012-10-09 @24 #define ELNRNG 41 /* Link number out of range */
61730c538f8281 David Howells 2012-10-09 @25 #define EUNATCH 42 /* Protocol driver not attached */
61730c538f8281 David Howells 2012-10-09 @26 #define ENOCSI 43 /* No CSI structure available */
61730c538f8281 David Howells 2012-10-09 @27 #define EL2HLT 44 /* Level 2 halted */
61730c538f8281 David Howells 2012-10-09 @28 #define EDEADLK 45 /* Resource deadlock would occur */
61730c538f8281 David Howells 2012-10-09 @29 #define ENOLCK 46 /* No record locks available */
61730c538f8281 David Howells 2012-10-09 @30 #define EBADE 50 /* Invalid exchange */
61730c538f8281 David Howells 2012-10-09 @31 #define EBADR 51 /* Invalid request descriptor */
61730c538f8281 David Howells 2012-10-09 @32 #define EXFULL 52 /* Exchange full */
61730c538f8281 David Howells 2012-10-09 @33 #define ENOANO 53 /* No anode */
61730c538f8281 David Howells 2012-10-09 @34 #define EBADRQC 54 /* Invalid request code */
61730c538f8281 David Howells 2012-10-09 @35 #define EBADSLT 55 /* Invalid slot */
61730c538f8281 David Howells 2012-10-09 @36 #define EDEADLOCK 56 /* File locking deadlock error */
61730c538f8281 David Howells 2012-10-09 37 #define EBFONT 59 /* Bad font file format */
61730c538f8281 David Howells 2012-10-09 38 #define ENOSTR 60 /* Device not a stream */
61730c538f8281 David Howells 2012-10-09 39 #define ENODATA 61 /* No data available */
61730c538f8281 David Howells 2012-10-09 40 #define ETIME 62 /* Timer expired */
61730c538f8281 David Howells 2012-10-09 41 #define ENOSR 63 /* Out of streams resources */
61730c538f8281 David Howells 2012-10-09 42 #define ENONET 64 /* Machine is not on the network */
61730c538f8281 David Howells 2012-10-09 43 #define ENOPKG 65 /* Package not installed */
61730c538f8281 David Howells 2012-10-09 44 #define EREMOTE 66 /* Object is remote */
61730c538f8281 David Howells 2012-10-09 45 #define ENOLINK 67 /* Link has been severed */
61730c538f8281 David Howells 2012-10-09 46 #define EADV 68 /* Advertise error */
61730c538f8281 David Howells 2012-10-09 47 #define ESRMNT 69 /* Srmount error */
61730c538f8281 David Howells 2012-10-09 48 #define ECOMM 70 /* Communication error on send */
61730c538f8281 David Howells 2012-10-09 49 #define EPROTO 71 /* Protocol error */
61730c538f8281 David Howells 2012-10-09 50 #define EDOTDOT 73 /* RFS specific error */
61730c538f8281 David Howells 2012-10-09 @51 #define EMULTIHOP 74 /* Multihop attempted */
61730c538f8281 David Howells 2012-10-09 @52 #define EBADMSG 77 /* Not a data message */
61730c538f8281 David Howells 2012-10-09 @53 #define ENAMETOOLONG 78 /* File name too long */
61730c538f8281 David Howells 2012-10-09 @54 #define EOVERFLOW 79 /* Value too large for defined data type */
61730c538f8281 David Howells 2012-10-09 @55 #define ENOTUNIQ 80 /* Name not unique on network */
61730c538f8281 David Howells 2012-10-09 @56 #define EBADFD 81 /* File descriptor in bad state */
61730c538f8281 David Howells 2012-10-09 @57 #define EREMCHG 82 /* Remote address changed */
61730c538f8281 David Howells 2012-10-09 @58 #define ELIBACC 83 /* Can not access a needed shared library */
61730c538f8281 David Howells 2012-10-09 @59 #define ELIBBAD 84 /* Accessing a corrupted shared library */
61730c538f8281 David Howells 2012-10-09 @60 #define ELIBSCN 85 /* .lib section in a.out corrupted */
61730c538f8281 David Howells 2012-10-09 @61 #define ELIBMAX 86 /* Attempting to link in too many shared libraries */
61730c538f8281 David Howells 2012-10-09 @62 #define ELIBEXEC 87 /* Cannot exec a shared library directly */
61730c538f8281 David Howells 2012-10-09 @63 #define EILSEQ 88 /* Illegal byte sequence */
61730c538f8281 David Howells 2012-10-09 @64 #define ENOSYS 89 /* Function not implemented */
61730c538f8281 David Howells 2012-10-09 @65 #define ELOOP 90 /* Too many symbolic links encountered */
61730c538f8281 David Howells 2012-10-09 @66 #define ERESTART 91 /* Interrupted system call should be restarted */
61730c538f8281 David Howells 2012-10-09 @67 #define ESTRPIPE 92 /* Streams pipe error */
61730c538f8281 David Howells 2012-10-09 @68 #define ENOTEMPTY 93 /* Directory not empty */
61730c538f8281 David Howells 2012-10-09 @69 #define EUSERS 94 /* Too many users */
61730c538f8281 David Howells 2012-10-09 @70 #define ENOTSOCK 95 /* Socket operation on non-socket */
61730c538f8281 David Howells 2012-10-09 @71 #define EDESTADDRREQ 96 /* Destination address required */
61730c538f8281 David Howells 2012-10-09 @72 #define EMSGSIZE 97 /* Message too long */
61730c538f8281 David Howells 2012-10-09 @73 #define EPROTOTYPE 98 /* Protocol wrong type for socket */
61730c538f8281 David Howells 2012-10-09 @74 #define ENOPROTOOPT 99 /* Protocol not available */
61730c538f8281 David Howells 2012-10-09 @75 #define EPROTONOSUPPORT 120 /* Protocol not supported */
61730c538f8281 David Howells 2012-10-09 @76 #define ESOCKTNOSUPPORT 121 /* Socket type not supported */
61730c538f8281 David Howells 2012-10-09 @77 #define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */
61730c538f8281 David Howells 2012-10-09 @78 #define EPFNOSUPPORT 123 /* Protocol family not supported */
61730c538f8281 David Howells 2012-10-09 @79 #define EAFNOSUPPORT 124 /* Address family not supported by protocol */
61730c538f8281 David Howells 2012-10-09 @80 #define EADDRINUSE 125 /* Address already in use */
61730c538f8281 David Howells 2012-10-09 @81 #define EADDRNOTAVAIL 126 /* Cannot assign requested address */
61730c538f8281 David Howells 2012-10-09 @82 #define ENETDOWN 127 /* Network is down */
61730c538f8281 David Howells 2012-10-09 @83 #define ENETUNREACH 128 /* Network is unreachable */
61730c538f8281 David Howells 2012-10-09 @84 #define ENETRESET 129 /* Network dropped connection because of reset */
61730c538f8281 David Howells 2012-10-09 @85 #define ECONNABORTED 130 /* Software caused connection abort */
61730c538f8281 David Howells 2012-10-09 @86 #define ECONNRESET 131 /* Connection reset by peer */
61730c538f8281 David Howells 2012-10-09 @87 #define ENOBUFS 132 /* No buffer space available */
61730c538f8281 David Howells 2012-10-09 @88 #define EISCONN 133 /* Transport endpoint is already connected */
61730c538f8281 David Howells 2012-10-09 @89 #define ENOTCONN 134 /* Transport endpoint is not connected */
61730c538f8281 David Howells 2012-10-09 @90 #define EUCLEAN 135 /* Structure needs cleaning */
61730c538f8281 David Howells 2012-10-09 @91 #define ENOTNAM 137 /* Not a XENIX named type file */
61730c538f8281 David Howells 2012-10-09 @92 #define ENAVAIL 138 /* No XENIX semaphores available */
61730c538f8281 David Howells 2012-10-09 @93 #define EISNAM 139 /* Is a named type file */
61730c538f8281 David Howells 2012-10-09 @94 #define EREMOTEIO 140 /* Remote I/O error */
61730c538f8281 David Howells 2012-10-09 95 #define EINIT 141 /* Reserved */
61730c538f8281 David Howells 2012-10-09 96 #define EREMDEV 142 /* Error 142 */
61730c538f8281 David Howells 2012-10-09 @97 #define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */
61730c538f8281 David Howells 2012-10-09 @98 #define ETOOMANYREFS 144 /* Too many references: cannot splice */
61730c538f8281 David Howells 2012-10-09 @99 #define ETIMEDOUT 145 /* Connection timed out */
61730c538f8281 David Howells 2012-10-09 @100 #define ECONNREFUSED 146 /* Connection refused */
61730c538f8281 David Howells 2012-10-09 @101 #define EHOSTDOWN 147 /* Host is down */
61730c538f8281 David Howells 2012-10-09 @102 #define EHOSTUNREACH 148 /* No route to host */
61730c538f8281 David Howells 2012-10-09 103 #define EWOULDBLOCK EAGAIN /* Operation would block */
61730c538f8281 David Howells 2012-10-09 @104 #define EALREADY 149 /* Operation already in progress */
61730c538f8281 David Howells 2012-10-09 @105 #define EINPROGRESS 150 /* Operation now in progress */
0ca43435188b9f Eric Sandeen 2013-11-12 @106 #define ESTALE 151 /* Stale file handle */
61730c538f8281 David Howells 2012-10-09 @107 #define ECANCELED 158 /* AIO operation canceled */
61730c538f8281 David Howells 2012-10-09 108
61730c538f8281 David Howells 2012-10-09 109 /*
61730c538f8281 David Howells 2012-10-09 110 * These error are Linux extensions.
61730c538f8281 David Howells 2012-10-09 111 */
61730c538f8281 David Howells 2012-10-09 @112 #define ENOMEDIUM 159 /* No medium found */
61730c538f8281 David Howells 2012-10-09 @113 #define EMEDIUMTYPE 160 /* Wrong medium type */
61730c538f8281 David Howells 2012-10-09 @114 #define ENOKEY 161 /* Required key not available */
61730c538f8281 David Howells 2012-10-09 @115 #define EKEYEXPIRED 162 /* Key has expired */
61730c538f8281 David Howells 2012-10-09 @116 #define EKEYREVOKED 163 /* Key has been revoked */
61730c538f8281 David Howells 2012-10-09 @117 #define EKEYREJECTED 164 /* Key was rejected by service */
61730c538f8281 David Howells 2012-10-09 118
61730c538f8281 David Howells 2012-10-09 119 /* for robust mutexes */
61730c538f8281 David Howells 2012-10-09 @120 #define EOWNERDEAD 165 /* Owner died */
61730c538f8281 David Howells 2012-10-09 @121 #define ENOTRECOVERABLE 166 /* State not recoverable */
61730c538f8281 David Howells 2012-10-09 122
61730c538f8281 David Howells 2012-10-09 @123 #define ERFKILL 167 /* Operation not possible due to RF-kill */
61730c538f8281 David Howells 2012-10-09 124
61730c538f8281 David Howells 2012-10-09 @125 #define EHWPOISON 168 /* Memory page has hardware error */
61730c538f8281 David Howells 2012-10-09 126
61730c538f8281 David Howells 2012-10-09 @127 #define EDQUOT 1133 /* Quota exceeded */
61730c538f8281 David Howells 2012-10-09 128
61730c538f8281 David Howells 2012-10-09 129
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Ryan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8]
url: https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-interrupt-controller-aspeed-Add-ASPEED-AST2700-INTC0-INTC1/20260205-141046
base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
patch link: https://lore.kernel.org/r/20260205-irqchip-v1-2-b0310e06c087%40aspeedtech.com
patch subject: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support
config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20260205/202602052259.vW8lLakZ-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602052259.vW8lLakZ-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/202602052259.vW8lLakZ-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from include/linux/err.h:8,
from include/linux/cleanup.h:6,
from include/linux/irqflags.h:17,
from include/asm-generic/cmpxchg-local.h:6,
from arch/parisc/include/asm/cmpxchg.h:87,
from arch/parisc/include/asm/atomic.h:10,
from include/linux/atomic.h:7,
from arch/parisc/include/asm/bitops.h:13,
from include/linux/bitops.h:67,
from drivers/irqchip/irq-ast2700-intc0.c:9:
>> arch/parisc/include/uapi/asm/errno.h:7:9: warning: 'ENOMSG' redefined
7 | #define ENOMSG 35 /* No message of desired type */
| ^~~~~~
In file included from drivers/irqchip/irq-ast2700-intc0.c:8:
include/uapi/asm-generic/errno.h:23:9: note: this is the location of the previous definition
23 | #define ENOMSG 42 /* No message of desired type */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:8:9: warning: 'EIDRM' redefined
8 | #define EIDRM 36 /* Identifier removed */
| ^~~~~
include/uapi/asm-generic/errno.h:24:9: note: this is the location of the previous definition
24 | #define EIDRM 43 /* Identifier removed */
| ^~~~~
>> arch/parisc/include/uapi/asm/errno.h:9:9: warning: 'ECHRNG' redefined
9 | #define ECHRNG 37 /* Channel number out of range */
| ^~~~~~
include/uapi/asm-generic/errno.h:25:9: note: this is the location of the previous definition
25 | #define ECHRNG 44 /* Channel number out of range */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:10:9: warning: 'EL2NSYNC' redefined
10 | #define EL2NSYNC 38 /* Level 2 not synchronized */
| ^~~~~~~~
include/uapi/asm-generic/errno.h:26:9: note: this is the location of the previous definition
26 | #define EL2NSYNC 45 /* Level 2 not synchronized */
| ^~~~~~~~
>> arch/parisc/include/uapi/asm/errno.h:11:9: warning: 'EL3HLT' redefined
11 | #define EL3HLT 39 /* Level 3 halted */
| ^~~~~~
include/uapi/asm-generic/errno.h:27:9: note: this is the location of the previous definition
27 | #define EL3HLT 46 /* Level 3 halted */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:12:9: warning: 'EL3RST' redefined
12 | #define EL3RST 40 /* Level 3 reset */
| ^~~~~~
include/uapi/asm-generic/errno.h:28:9: note: this is the location of the previous definition
28 | #define EL3RST 47 /* Level 3 reset */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:13:9: warning: 'ELNRNG' redefined
13 | #define ELNRNG 41 /* Link number out of range */
| ^~~~~~
include/uapi/asm-generic/errno.h:29:9: note: this is the location of the previous definition
29 | #define ELNRNG 48 /* Link number out of range */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:14:9: warning: 'EUNATCH' redefined
14 | #define EUNATCH 42 /* Protocol driver not attached */
| ^~~~~~~
include/uapi/asm-generic/errno.h:30:9: note: this is the location of the previous definition
30 | #define EUNATCH 49 /* Protocol driver not attached */
| ^~~~~~~
>> arch/parisc/include/uapi/asm/errno.h:15:9: warning: 'ENOCSI' redefined
15 | #define ENOCSI 43 /* No CSI structure available */
| ^~~~~~
include/uapi/asm-generic/errno.h:31:9: note: this is the location of the previous definition
31 | #define ENOCSI 50 /* No CSI structure available */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:16:9: warning: 'EL2HLT' redefined
16 | #define EL2HLT 44 /* Level 2 halted */
| ^~~~~~
include/uapi/asm-generic/errno.h:32:9: note: this is the location of the previous definition
32 | #define EL2HLT 51 /* Level 2 halted */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:17:9: warning: 'EDEADLK' redefined
17 | #define EDEADLK 45 /* Resource deadlock would occur */
| ^~~~~~~
include/uapi/asm-generic/errno.h:7:9: note: this is the location of the previous definition
7 | #define EDEADLK 35 /* Resource deadlock would occur */
| ^~~~~~~
>> arch/parisc/include/uapi/asm/errno.h:19:9: warning: 'ENOLCK' redefined
19 | #define ENOLCK 46 /* No record locks available */
| ^~~~~~
include/uapi/asm-generic/errno.h:9:9: note: this is the location of the previous definition
9 | #define ENOLCK 37 /* No record locks available */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:20:9: warning: 'EILSEQ' redefined
20 | #define EILSEQ 47 /* Illegal byte sequence */
| ^~~~~~
include/uapi/asm-generic/errno.h:67:9: note: this is the location of the previous definition
67 | #define EILSEQ 84 /* Illegal byte sequence */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:22:9: warning: 'ENONET' redefined
22 | #define ENONET 50 /* Machine is not on the network */
| ^~~~~~
include/uapi/asm-generic/errno.h:47:9: note: this is the location of the previous definition
47 | #define ENONET 64 /* Machine is not on the network */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:23:9: warning: 'ENODATA' redefined
23 | #define ENODATA 51 /* No data available */
| ^~~~~~~
include/uapi/asm-generic/errno.h:44:9: note: this is the location of the previous definition
44 | #define ENODATA 61 /* No data available */
| ^~~~~~~
>> arch/parisc/include/uapi/asm/errno.h:24:9: warning: 'ETIME' redefined
24 | #define ETIME 52 /* Timer expired */
| ^~~~~
include/uapi/asm-generic/errno.h:45:9: note: this is the location of the previous definition
45 | #define ETIME 62 /* Timer expired */
| ^~~~~
>> arch/parisc/include/uapi/asm/errno.h:25:9: warning: 'ENOSR' redefined
25 | #define ENOSR 53 /* Out of streams resources */
| ^~~~~
include/uapi/asm-generic/errno.h:46:9: note: this is the location of the previous definition
46 | #define ENOSR 63 /* Out of streams resources */
| ^~~~~
>> arch/parisc/include/uapi/asm/errno.h:26:9: warning: 'ENOSTR' redefined
26 | #define ENOSTR 54 /* Device not a stream */
| ^~~~~~
include/uapi/asm-generic/errno.h:43:9: note: this is the location of the previous definition
43 | #define ENOSTR 60 /* Device not a stream */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:27:9: warning: 'ENOPKG' redefined
27 | #define ENOPKG 55 /* Package not installed */
| ^~~~~~
include/uapi/asm-generic/errno.h:48:9: note: this is the location of the previous definition
48 | #define ENOPKG 65 /* Package not installed */
| ^~~~~~
>> arch/parisc/include/uapi/asm/errno.h:29:9: warning: 'ENOLINK' redefined
29 | #define ENOLINK 57 /* Link has been severed */
| ^~~~~~~
include/uapi/asm-generic/errno.h:50:9: note: this is the location of the previous definition
50 | #define ENOLINK 67 /* Link has been severed */
| ^~~~~~~
arch/parisc/include/uapi/asm/errno.h:30:9: warning: 'EADV' redefined
30 | #define EADV 58 /* Advertise error */
| ^~~~
include/uapi/asm-generic/errno.h:51:9: note: this is the location of the previous definition
51 | #define EADV 68 /* Advertise error */
| ^~~~
arch/parisc/include/uapi/asm/errno.h:31:9: warning: 'ESRMNT' redefined
31 | #define ESRMNT 59 /* Srmount error */
| ^~~~~~
include/uapi/asm-generic/errno.h:52:9: note: this is the location of the previous definition
52 | #define ESRMNT 69 /* Srmount error */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:32:9: warning: 'ECOMM' redefined
32 | #define ECOMM 60 /* Communication error on send */
| ^~~~~
include/uapi/asm-generic/errno.h:53:9: note: this is the location of the previous definition
53 | #define ECOMM 70 /* Communication error on send */
| ^~~~~
arch/parisc/include/uapi/asm/errno.h:33:9: warning: 'EPROTO' redefined
33 | #define EPROTO 61 /* Protocol error */
| ^~~~~~
include/uapi/asm-generic/errno.h:54:9: note: this is the location of the previous definition
54 | #define EPROTO 71 /* Protocol error */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:35:9: warning: 'EMULTIHOP' redefined
35 | #define EMULTIHOP 64 /* Multihop attempted */
| ^~~~~~~~~
include/uapi/asm-generic/errno.h:55:9: note: this is the location of the previous definition
55 | #define EMULTIHOP 72 /* Multihop attempted */
| ^~~~~~~~~
arch/parisc/include/uapi/asm/errno.h:37:9: warning: 'EDOTDOT' redefined
37 | #define EDOTDOT 66 /* RFS specific error */
| ^~~~~~~
include/uapi/asm-generic/errno.h:56:9: note: this is the location of the previous definition
56 | #define EDOTDOT 73 /* RFS specific error */
| ^~~~~~~
arch/parisc/include/uapi/asm/errno.h:38:9: warning: 'EBADMSG' redefined
38 | #define EBADMSG 67 /* Not a data message */
| ^~~~~~~
include/uapi/asm-generic/errno.h:57:9: note: this is the location of the previous definition
57 | #define EBADMSG 74 /* Not a data message */
| ^~~~~~~
arch/parisc/include/uapi/asm/errno.h:39:9: warning: 'EUSERS' redefined
39 | #define EUSERS 68 /* Too many users */
| ^~~~~~
include/uapi/asm-generic/errno.h:70:9: note: this is the location of the previous definition
70 | #define EUSERS 87 /* Too many users */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:40:9: warning: 'EDQUOT' redefined
40 | #define EDQUOT 69 /* Quota exceeded */
| ^~~~~~
include/uapi/asm-generic/errno.h:105:9: note: this is the location of the previous definition
105 | #define EDQUOT 122 /* Quota exceeded */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:41:9: warning: 'ESTALE' redefined
41 | #define ESTALE 70 /* Stale file handle */
| ^~~~~~
include/uapi/asm-generic/errno.h:99:9: note: this is the location of the previous definition
99 | #define ESTALE 116 /* Stale file handle */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:42:9: warning: 'EREMOTE' redefined
42 | #define EREMOTE 71 /* Object is remote */
| ^~~~~~~
include/uapi/asm-generic/errno.h:49:9: note: this is the location of the previous definition
49 | #define EREMOTE 66 /* Object is remote */
| ^~~~~~~
arch/parisc/include/uapi/asm/errno.h:43:9: warning: 'EOVERFLOW' redefined
43 | #define EOVERFLOW 72 /* Value too large for defined data type */
| ^~~~~~~~~
include/uapi/asm-generic/errno.h:58:9: note: this is the location of the previous definition
58 | #define EOVERFLOW 75 /* Value too large for defined data type */
| ^~~~~~~~~
arch/parisc/include/uapi/asm/errno.h:47:9: warning: 'EBADE' redefined
47 | #define EBADE 160 /* Invalid exchange */
| ^~~~~
include/uapi/asm-generic/errno.h:33:9: note: this is the location of the previous definition
33 | #define EBADE 52 /* Invalid exchange */
| ^~~~~
arch/parisc/include/uapi/asm/errno.h:48:9: warning: 'EBADR' redefined
48 | #define EBADR 161 /* Invalid request descriptor */
| ^~~~~
include/uapi/asm-generic/errno.h:34:9: note: this is the location of the previous definition
34 | #define EBADR 53 /* Invalid request descriptor */
| ^~~~~
arch/parisc/include/uapi/asm/errno.h:49:9: warning: 'EXFULL' redefined
49 | #define EXFULL 162 /* Exchange full */
| ^~~~~~
include/uapi/asm-generic/errno.h:35:9: note: this is the location of the previous definition
35 | #define EXFULL 54 /* Exchange full */
| ^~~~~~
arch/parisc/include/uapi/asm/errno.h:50:9: warning: 'ENOANO' redefined
50 | #define ENOANO 163 /* No anode */
| ^~~~~~
include/uapi/asm-generic/errno.h:36:9: note: this is the location of the previous definition
36 | #define ENOANO 55 /* No anode */
vim +/ENOMSG +7 arch/parisc/include/uapi/asm/errno.h
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 6
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @7 #define ENOMSG 35 /* No message of desired type */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @8 #define EIDRM 36 /* Identifier removed */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @9 #define ECHRNG 37 /* Channel number out of range */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @10 #define EL2NSYNC 38 /* Level 2 not synchronized */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @11 #define EL3HLT 39 /* Level 3 halted */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @12 #define EL3RST 40 /* Level 3 reset */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @13 #define ELNRNG 41 /* Link number out of range */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @14 #define EUNATCH 42 /* Protocol driver not attached */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @15 #define ENOCSI 43 /* No CSI structure available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @16 #define EL2HLT 44 /* Level 2 halted */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @17 #define EDEADLK 45 /* Resource deadlock would occur */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 18 #define EDEADLOCK EDEADLK
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @19 #define ENOLCK 46 /* No record locks available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @20 #define EILSEQ 47 /* Illegal byte sequence */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 21
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @22 #define ENONET 50 /* Machine is not on the network */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @23 #define ENODATA 51 /* No data available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @24 #define ETIME 52 /* Timer expired */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @25 #define ENOSR 53 /* Out of streams resources */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @26 #define ENOSTR 54 /* Device not a stream */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @27 #define ENOPKG 55 /* Package not installed */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 28
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @29 #define ENOLINK 57 /* Link has been severed */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @30 #define EADV 58 /* Advertise error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @31 #define ESRMNT 59 /* Srmount error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @32 #define ECOMM 60 /* Communication error on send */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @33 #define EPROTO 61 /* Protocol error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 34
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @35 #define EMULTIHOP 64 /* Multihop attempted */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 36
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @37 #define EDOTDOT 66 /* RFS specific error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @38 #define EBADMSG 67 /* Not a data message */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @39 #define EUSERS 68 /* Too many users */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @40 #define EDQUOT 69 /* Quota exceeded */
0ca43435188b9f9 arch/parisc/include/uapi/asm/errno.h Eric Sandeen 2013-11-12 @41 #define ESTALE 70 /* Stale file handle */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @42 #define EREMOTE 71 /* Object is remote */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @43 #define EOVERFLOW 72 /* Value too large for defined data type */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 44
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 45 /* these errnos are defined by Linux but not HPUX. */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 46
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @47 #define EBADE 160 /* Invalid exchange */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @48 #define EBADR 161 /* Invalid request descriptor */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @49 #define EXFULL 162 /* Exchange full */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @50 #define ENOANO 163 /* No anode */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @51 #define EBADRQC 164 /* Invalid request code */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @52 #define EBADSLT 165 /* Invalid slot */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @53 #define EBFONT 166 /* Bad font file format */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @54 #define ENOTUNIQ 167 /* Name not unique on network */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @55 #define EBADFD 168 /* File descriptor in bad state */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @56 #define EREMCHG 169 /* Remote address changed */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @57 #define ELIBACC 170 /* Can not access a needed shared library */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @58 #define ELIBBAD 171 /* Accessing a corrupted shared library */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @59 #define ELIBSCN 172 /* .lib section in a.out corrupted */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @60 #define ELIBMAX 173 /* Attempting to link in too many shared libraries */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @61 #define ELIBEXEC 174 /* Cannot exec a shared library directly */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @62 #define ERESTART 175 /* Interrupted system call should be restarted */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @63 #define ESTRPIPE 176 /* Streams pipe error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @64 #define EUCLEAN 177 /* Structure needs cleaning */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @65 #define ENOTNAM 178 /* Not a XENIX named type file */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @66 #define ENAVAIL 179 /* No XENIX semaphores available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @67 #define EISNAM 180 /* Is a named type file */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @68 #define EREMOTEIO 181 /* Remote I/O error */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @69 #define ENOMEDIUM 182 /* No medium found */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @70 #define EMEDIUMTYPE 183 /* Wrong medium type */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @71 #define ENOKEY 184 /* Required key not available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @72 #define EKEYEXPIRED 185 /* Key has expired */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @73 #define EKEYREVOKED 186 /* Key has been revoked */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @74 #define EKEYREJECTED 187 /* Key was rejected by service */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 75
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 76 /* We now return you to your regularly scheduled HPUX. */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 77
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @78 #define ENOTSOCK 216 /* Socket operation on non-socket */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @79 #define EDESTADDRREQ 217 /* Destination address required */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @80 #define EMSGSIZE 218 /* Message too long */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @81 #define EPROTOTYPE 219 /* Protocol wrong type for socket */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @82 #define ENOPROTOOPT 220 /* Protocol not available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @83 #define EPROTONOSUPPORT 221 /* Protocol not supported */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @84 #define ESOCKTNOSUPPORT 222 /* Socket type not supported */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @85 #define EOPNOTSUPP 223 /* Operation not supported on transport endpoint */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @86 #define EPFNOSUPPORT 224 /* Protocol family not supported */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @87 #define EAFNOSUPPORT 225 /* Address family not supported by protocol */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @88 #define EADDRINUSE 226 /* Address already in use */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @89 #define EADDRNOTAVAIL 227 /* Cannot assign requested address */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @90 #define ENETDOWN 228 /* Network is down */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @91 #define ENETUNREACH 229 /* Network is unreachable */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @92 #define ENETRESET 230 /* Network dropped connection because of reset */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @93 #define ECONNABORTED 231 /* Software caused connection abort */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @94 #define ECONNRESET 232 /* Connection reset by peer */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @95 #define ENOBUFS 233 /* No buffer space available */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @96 #define EISCONN 234 /* Transport endpoint is already connected */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @97 #define ENOTCONN 235 /* Transport endpoint is not connected */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @98 #define ESHUTDOWN 236 /* Cannot send after transport endpoint shutdown */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @99 #define ETOOMANYREFS 237 /* Too many references: cannot splice */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @100 #define ETIMEDOUT 238 /* Connection timed out */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @101 #define ECONNREFUSED 239 /* Connection refused */
3eb53b20d7bd137 arch/parisc/include/uapi/asm/errno.h Helge Deller 2016-08-20 102 #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @103 #define EHOSTDOWN 241 /* Host is down */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @104 #define EHOSTUNREACH 242 /* No route to host */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 105
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @106 #define EALREADY 244 /* Operation already in progress */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @107 #define EINPROGRESS 245 /* Operation now in progress */
f5a408d53edef3a arch/parisc/include/uapi/asm/errno.h Guy Martin 2014-01-16 108 #define EWOULDBLOCK EAGAIN /* Operation would block (Not HPUX compliant) */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @109 #define ENOTEMPTY 247 /* Directory not empty */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @110 #define ENAMETOOLONG 248 /* File name too long */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @111 #define ELOOP 249 /* Too many symbolic links encountered */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @112 #define ENOSYS 251 /* Function not implemented */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 113
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 114 #define ECANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */
05aa10de701409b include/asm-parisc/errno.h Grant Grundler 2005-10-21 @115 #define ECANCELED ECANCELLED /* SuSv3 and Solaris wants one 'L' */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 116
4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 117 /* for robust mutexes */
4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 @118 #define EOWNERDEAD 254 /* Owner died */
4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 @119 #define ENOTRECOVERABLE 255 /* State not recoverable */
4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 120
7d217d7ffc3433d arch/parisc/include/asm/errno.h Alexander Beregalov 2009-06-07 @121 #define ERFKILL 256 /* Operation not possible due to RF-kill */
^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 122
69ebb83e13e5142 arch/parisc/include/asm/errno.h Ying Huang 2011-01-30 @123 #define EHWPOISON 257 /* Memory page has hardware error */
69ebb83e13e5142 arch/parisc/include/asm/errno.h Ying Huang 2011-01-30 124
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2026 Red Hat, Inc.