* [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver
@ 2026-11-12 22:44 Rosen Penev
2026-11-12 22:44 ` [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested Rosen Penev
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Rosen Penev @ 2026-11-12 22:44 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Bogendoerfer, Thomas Gleixner
Cc: Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Radu Rendec, linux-perf-users,
linux-kernel, linux-mips
The MISC interrupt controller of the Atheros/Qualcomm ath79 SoCs is
cascaded from a CPU interrupt, and all of its users are platform
devices. It is still initialized from IRQCHIP_DECLARE, before the early
initcalls, only because the MIPS perf code asks for the performance
counter overflow interrupt, which goes through it, from an
early_initcall.
Patch 1 makes the MIPS perf code look up that interrupt when the first
event is created, which is when it is requested. Patch 2 makes the ath79
MISC driver create the mapping at that point. Patch 3 then converts the
driver to IRQCHIP_PLATFORM_DRIVER with device-managed resources, which
also fixes the leak of the register mapping on its error path. Patch 4
adds COMPILE_TEST coverage, which a platform driver makes possible.
Patch 3 depends on patch 1: without it, perf would ask for the interrupt
before the controller has probed and would lose its overflow interrupt.
Patch 1 touches only arch/mips, so the series could go through the MIPS
tree with an ack for the irqchip patches, or through irqchip with an ack
for patch 1.
The other users of get_c0_perfcount_int() (generic/GIC, Malta, Lantiq,
Ralink) return an interrupt that is set up at boot, so calling it later
does not change anything for them. The perf boot message no longer
prints the interrupt, which is not known at that point.
Tested on a TP-Link Archer C7 v2 (QCA9558), with the device tree from
the pending series that adds it: the MISC controller probes as a
platform device, its users (UART, GPIO, watchdog) probe with nothing
left deferred, and perf record gets its samples from the overflow
interrupt on MISC 5. Each patch builds with W=1 (mips, clang), and
with patch 4 the driver also builds with W=1 for arm64, x86_64 and a
non-ath79 MIPS kernel (Lantiq).
An AI coding assistant (Claude Code, Claude Opus 5.5) was used to write
the patches, test them on the router over its serial console, and draft
the commit messages and this cover letter.
Rosen Penev (4):
MIPS: perf: look up the PMU interrupt when it is requested
irqchip/ath79-misc: map the performance counter interrupt on demand
irqchip/ath79-misc: convert to a platform driver
irqchip/ath79-misc: allow COMPILE_TEST builds
arch/mips/kernel/perf_event_mipsxx.c | 30 +++++---
drivers/irqchip/Kconfig | 14 ++++
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-ath79-misc.c | 108 ++++++++++++++-------------
4 files changed, 88 insertions(+), 66 deletions(-)
base-commit: aaa2f954c21b205a0bcd0961e5b2be4e82e58455
--
2.56.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested
2026-11-12 22:44 [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver Rosen Penev
@ 2026-11-12 22:44 ` Rosen Penev
2026-11-12 22:55 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand Rosen Penev
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Rosen Penev @ 2026-11-12 22:44 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Bogendoerfer, Thomas Gleixner
Cc: Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Radu Rendec, linux-perf-users,
linux-kernel, linux-mips
init_hw_perf_events() is an early_initcall and asks the platform for
the counter overflow interrupt through get_c0_perfcount_int(). On
ath79, that interrupt goes through the MISC interrupt controller, so
the controller has to be initialized from IRQCHIP_DECLARE before the
early initcalls, even though nothing else needs it that early.
The interrupt is only requested when the first event is created. Look
it up then, so that it can come from an interrupt controller probed as
a platform driver. The boot message no longer prints the interrupt.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
arch/mips/kernel/perf_event_mipsxx.c | 30 +++++++++++++++++-----------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 196a070349b0..4d660952e643 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -589,10 +589,25 @@ static atomic_t active_events = ATOMIC_INIT(0);
static DEFINE_MUTEX(pmu_reserve_mutex);
static int (*save_perf_irq)(void);
+/*
+ * The interrupt is looked up when the first event is created, not when the
+ * PMU is registered: on some platforms, the interrupt controller that the
+ * counter overflow is wired to is only probed after the early initcalls.
+ */
+static int mipspmu_find_irq(void)
+{
+ if (get_c0_perfcount_int)
+ return get_c0_perfcount_int();
+ if (cp0_perfcount_irq >= 0)
+ return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+ return -1;
+}
+
static int mipspmu_get_irq(void)
{
int err;
+ mipspmu.irq = mipspmu_find_irq();
if (mipspmu.irq >= 0) {
/* Request my own irq handler. */
err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq,
@@ -1889,7 +1904,7 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
static int __init
init_hw_perf_events(void)
{
- int counters, irq, pmu_type;
+ int counters, pmu_type;
pr_info("Performance counters: ");
@@ -1904,13 +1919,6 @@ init_hw_perf_events(void)
counters = counters_total_to_per_cpu(counters);
#endif
- if (get_c0_perfcount_int)
- irq = get_c0_perfcount_int();
- else if (cp0_perfcount_irq >= 0)
- irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
- else
- irq = -1;
-
mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
switch (current_cpu_type()) {
@@ -2017,7 +2025,6 @@ init_hw_perf_events(void)
}
mipspmu.num_counters = counters;
- mipspmu.irq = irq;
if (read_c0_perfctrl0() & MIPS_PERFCTRL_W) {
if (get_loongson3_pmu_type() == LOONGSON_PMU_TYPE2) {
@@ -2044,9 +2051,8 @@ init_hw_perf_events(void)
on_each_cpu(reset_counters, (void *)(long)counters, 1);
- pr_cont("%s PMU enabled, %d %d-bit counters available to each "
- "CPU, irq %d%s\n", mipspmu.name, counters, counter_bits, irq,
- irq < 0 ? " (share with timer interrupt)" : "");
+ pr_cont("%s PMU enabled, %d %d-bit counters available to each CPU\n",
+ mipspmu.name, counters, counter_bits);
perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
--
2.56.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand
2026-11-12 22:44 [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver Rosen Penev
2026-11-12 22:44 ` [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested Rosen Penev
@ 2026-11-12 22:44 ` Rosen Penev
2026-11-12 22:52 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver Rosen Penev
2026-11-12 22:44 ` [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds Rosen Penev
3 siblings, 1 reply; 9+ messages in thread
From: Rosen Penev @ 2026-11-12 22:44 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Bogendoerfer, Thomas Gleixner
Cc: Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Radu Rendec, linux-perf-users,
linux-kernel, linux-mips
The MIPS perf code now asks for the counter overflow interrupt when the
first event is created, instead of from an early_initcall. Create the
mapping in get_c0_perfcount_int() then, instead of when the controller
is initialized, so that the controller no longer has to be ready before
the early initcalls.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/irqchip/irq-ath79-misc.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c
index 258b8e9a2d57..5cedea5234e0 100644
--- a/drivers/irqchip/irq-ath79-misc.c
+++ b/drivers/irqchip/irq-ath79-misc.c
@@ -23,11 +23,19 @@
#define ATH79_MISC_IRQ_COUNT 32
#define ATH79_MISC_PERF_IRQ 5
-static int ath79_perfcount_irq;
+static struct irq_domain *ath79_misc_domain;
+/* Called by the MIPS perf code when the first event is created. */
int get_c0_perfcount_int(void)
{
- return ath79_perfcount_irq;
+ unsigned int irq;
+
+ if (!ath79_misc_domain)
+ return -1;
+
+ irq = irq_create_mapping(ath79_misc_domain, ATH79_MISC_PERF_IRQ);
+
+ return irq ? irq : -1;
}
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
@@ -121,8 +129,6 @@ static void __init ath79_misc_intc_domain_init(
{
void __iomem *base = domain->host_data;
- ath79_perfcount_irq = irq_create_mapping(domain, ATH79_MISC_PERF_IRQ);
-
/* Disable and clear all interrupts */
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
@@ -157,6 +163,7 @@ static int __init ath79_misc_intc_of_init(
}
ath79_misc_intc_domain_init(domain, irq);
+ ath79_misc_domain = domain;
return 0;
}
--
2.56.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver
2026-11-12 22:44 [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver Rosen Penev
2026-11-12 22:44 ` [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested Rosen Penev
2026-11-12 22:44 ` [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand Rosen Penev
@ 2026-11-12 22:44 ` Rosen Penev
2026-11-12 23:00 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds Rosen Penev
3 siblings, 1 reply; 9+ messages in thread
From: Rosen Penev @ 2026-11-12 22:44 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Bogendoerfer, Thomas Gleixner
Cc: Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Radu Rendec, linux-perf-users,
linux-kernel, linux-mips
The MISC interrupt controller is cascaded from a CPU interrupt, and its
users are all platform devices, which defer their probe until it is
available. The performance counter interrupt, the only one needed
before the early initcalls, is now mapped on demand.
Probe the controller as a platform driver, and use device-managed
resources, which also fixes the leak of the register mapping when the
irq domain cannot be created.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/irqchip/irq-ath79-misc.c | 78 ++++++++++++++------------------
1 file changed, 34 insertions(+), 44 deletions(-)
diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c
index 5cedea5234e0..b06ece446746 100644
--- a/drivers/irqchip/irq-ath79-misc.c
+++ b/drivers/irqchip/irq-ath79-misc.c
@@ -12,8 +12,9 @@
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <asm/time.h>
@@ -124,65 +125,54 @@ static const struct irq_domain_ops misc_irq_domain_ops = {
.map = misc_map,
};
-static void __init ath79_misc_intc_domain_init(
- struct irq_domain *domain, int irq)
-{
- void __iomem *base = domain->host_data;
-
- /* Disable and clear all interrupts */
- __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
- __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
-
- irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
-}
-
-static int __init ath79_misc_intc_of_init(
- struct device_node *node, struct device_node *parent)
+static int ath79_misc_intc_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct irq_domain *domain;
void __iomem *base;
int irq;
- irq = irq_of_parse_and_map(node, 0);
- if (!irq) {
- pr_err("Failed to get MISC IRQ\n");
- return -EINVAL;
- }
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
- base = of_iomap(node, 0);
- if (!base) {
- pr_err("Failed to get MISC IRQ registers\n");
- return -ENOMEM;
- }
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- domain = irq_domain_create_linear(of_fwnode_handle(node), ATH79_MISC_IRQ_COUNT,
- &misc_irq_domain_ops, base);
- if (!domain) {
- pr_err("Failed to add MISC irqdomain\n");
- return -EINVAL;
- }
+ domain = devm_irq_domain_create_linear(dev, dev_fwnode(dev),
+ ATH79_MISC_IRQ_COUNT,
+ &misc_irq_domain_ops, base);
+ if (!domain)
+ return dev_err_probe(dev, -ENOMEM, "failed to add the irq domain\n");
+
+ /* Disable and clear all interrupts */
+ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
- ath79_misc_intc_domain_init(domain, irq);
+ irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
ath79_misc_domain = domain;
+
return 0;
}
-static int __init ar7100_misc_intc_of_init(
- struct device_node *node, struct device_node *parent)
+static int ar7100_misc_intc_probe(struct platform_device *pdev,
+ struct device_node *parent)
{
ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
- return ath79_misc_intc_of_init(node, parent);
+ return ath79_misc_intc_probe(pdev);
}
-IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
- ar7100_misc_intc_of_init);
-
-static int __init ar7240_misc_intc_of_init(
- struct device_node *node, struct device_node *parent)
+static int ar7240_misc_intc_probe(struct platform_device *pdev,
+ struct device_node *parent)
{
ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
- return ath79_misc_intc_of_init(node, parent);
+ return ath79_misc_intc_probe(pdev);
}
-IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
- ar7240_misc_intc_of_init);
+IRQCHIP_PLATFORM_DRIVER_BEGIN(ath79_misc_intc)
+IRQCHIP_MATCH("qca,ar7100-misc-intc", ar7100_misc_intc_probe)
+IRQCHIP_MATCH("qca,ar7240-misc-intc", ar7240_misc_intc_probe)
+IRQCHIP_PLATFORM_DRIVER_END(ath79_misc_intc)
+MODULE_DESCRIPTION("Atheros AR71xx/AR724x/AR913x MISC interrupt controller");
+MODULE_LICENSE("GPL");
--
2.56.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds
2026-11-12 22:44 [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver Rosen Penev
` (2 preceding siblings ...)
2026-11-12 22:44 ` [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver Rosen Penev
@ 2026-11-12 22:44 ` Rosen Penev
2026-11-12 22:51 ` sashiko-bot
3 siblings, 1 reply; 9+ messages in thread
From: Rosen Penev @ 2026-11-12 22:44 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Bogendoerfer, Thomas Gleixner
Cc: Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Radu Rendec, linux-perf-users,
linux-kernel, linux-mips
The driver is only built with ATH79, so only ath79 kernels build it. As
a platform driver, its only MIPS-specific parts are the performance
counter hook and the call to spurious_interrupt().
Add a Kconfig symbol that defaults to ATH79 and can be enabled with
COMPILE_TEST. Build the performance counter hook only with ATH79, as
other MIPS platforms provide their own. Drop the call to
spurious_interrupt(), which only exists on MIPS: a cascaded interrupt
with nothing pending only bumped the error count in /proc/interrupts,
and the handler now just returns.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/irqchip/Kconfig | 14 ++++++++++++++
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-ath79-misc.c | 19 ++++++++++++-------
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 731041def5d6..91fcc433afab 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -127,6 +127,20 @@ config ASPEED_AST2700_INTC_TEST
If unsure, say N.
+config ATH79_MISC_IRQ
+ bool "Atheros/Qualcomm ath79 MISC interrupt controller" if COMPILE_TEST
+ depends on ATH79 || COMPILE_TEST
+ depends on OF
+ depends on HAS_IOMEM
+ default ATH79
+ select IRQ_DOMAIN
+ help
+ Support the MISC interrupt controller of the Atheros/Qualcomm
+ ath79 SoCs. It is cascaded from a CPU interrupt and collects the
+ interrupts of the UART, GPIO, timers, watchdog and performance
+ counters, among others. It is enabled by default on ath79, and
+ only needs to be selected by hand for compile testing.
+
config ATMEL_AIC_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 16a5fd126c9a..de7be9803c74 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o
obj-$(CONFIG_AL_FIC) += irq-al-fic.o
obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o
obj-$(CONFIG_ATH79) += irq-ath79-cpu.o
-obj-$(CONFIG_ATH79) += irq-ath79-misc.o
+obj-$(CONFIG_ATH79_MISC_IRQ) += irq-ath79-misc.o
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
obj-$(CONFIG_ARCH_ACTIONS) += irq-owl-sirq.o
diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c
index b06ece446746..dc865dbbbc3b 100644
--- a/drivers/irqchip/irq-ath79-misc.c
+++ b/drivers/irqchip/irq-ath79-misc.c
@@ -16,7 +16,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#ifdef CONFIG_ATH79
#include <asm/time.h>
+#endif
#define AR71XX_RESET_REG_MISC_INT_STATUS 0
#define AR71XX_RESET_REG_MISC_INT_ENABLE 4
@@ -24,8 +26,14 @@
#define ATH79_MISC_IRQ_COUNT 32
#define ATH79_MISC_PERF_IRQ 5
+#ifdef CONFIG_ATH79
static struct irq_domain *ath79_misc_domain;
+static void ath79_misc_set_perf_domain(struct irq_domain *domain)
+{
+ ath79_misc_domain = domain;
+}
+
/* Called by the MIPS perf code when the first event is created. */
int get_c0_perfcount_int(void)
{
@@ -39,6 +47,9 @@ int get_c0_perfcount_int(void)
return irq ? irq : -1;
}
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+#else
+static void ath79_misc_set_perf_domain(struct irq_domain *domain) { }
+#endif
static void ath79_misc_irq_handler(struct irq_desc *desc)
{
@@ -52,12 +63,6 @@ static void ath79_misc_irq_handler(struct irq_desc *desc)
pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
- if (!pending) {
- spurious_interrupt();
- chained_irq_exit(chip, desc);
- return;
- }
-
while (pending) {
int bit = __ffs(pending);
@@ -151,7 +156,7 @@ static int ath79_misc_intc_probe(struct platform_device *pdev)
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
- ath79_misc_domain = domain;
+ ath79_misc_set_perf_domain(domain);
return 0;
}
--
2.56.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds
2026-11-12 22:44 ` [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds Rosen Penev
@ 2026-11-12 22:51 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-11-12 22:51 UTC (permalink / raw)
To: Rosen Penev; +Cc: linux-perf-users
> The driver is only built with ATH79, so only ath79 kernels build it. As
> a platform driver, its only MIPS-specific parts are the performance
> counter hook and the call to spurious_interrupt().
>
> Add a Kconfig symbol that defaults to ATH79 and can be enabled with
> COMPILE_TEST. Build the performance counter hook only with ATH79, as
> other MIPS platforms provide their own. Drop the call to
> spurious_interrupt(), which only exists on MIPS: a cascaded interrupt
> with nothing pending only bumped the error count in /proc/interrupts,
> and the handler now just returns.
>
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112224445.213324-1-rosenp@gmail.com?part=4
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand
2026-11-12 22:44 ` [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand Rosen Penev
@ 2026-11-12 22:52 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-11-12 22:52 UTC (permalink / raw)
To: Rosen Penev; +Cc: linux-perf-users
> The MIPS perf code now asks for the counter overflow interrupt when the
> first event is created, instead of from an early_initcall. Create the
> mapping in get_c0_perfcount_int() then, instead of when the controller
> is initialized, so that the controller no longer has to be ready before
> the early initcalls.
>
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112224445.213324-1-rosenp@gmail.com?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested
2026-11-12 22:44 ` [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested Rosen Penev
@ 2026-11-12 22:55 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-11-12 22:55 UTC (permalink / raw)
To: Rosen Penev; +Cc: linux-perf-users
> init_hw_perf_events() is an early_initcall and asks the platform for
> the counter overflow interrupt through get_c0_perfcount_int(). On
> ath79, that interrupt goes through the MISC interrupt controller, so
> the controller has to be initialized from IRQCHIP_DECLARE before the
> early initcalls, even though nothing else needs it that early.
>
> The interrupt is only requested when the first event is created. Look
> it up then, so that it can come from an interrupt controller probed as
> a platform driver. The boot message no longer prints the interrupt.
>
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112224445.213324-1-rosenp@gmail.com?part=1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver
2026-11-12 22:44 ` [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver Rosen Penev
@ 2026-11-12 23:00 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-11-12 23:00 UTC (permalink / raw)
To: Rosen Penev; +Cc: linux-perf-users
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [High] irqchip/ath79-misc: ath79_misc_intc_probe() clobbers QCA956x
timer mask
--
commit 60ba869db8725142b0f8869ed514d502d7719988
Author: Rosen Penev <rosenp@gmail.com>
irqchip/ath79-misc: convert to a platform driver
This commit converts the ath79-misc interrupt controller driver from
IRQCHIP_DECLARE() to a platform driver using device-managed resources.
> diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c
> index 5cedea5234e05..b06ece446746c 100644
> --- a/drivers/irqchip/irq-ath79-misc.c
> +++ b/drivers/irqchip/irq-ath79-misc.c
[ ... ]
> @@ -124,65 +125,54 @@ static const struct irq_domain_ops misc_irq_domain_ops = {
> .map = misc_map,
> };
>
> -static void __init ath79_misc_intc_domain_init(
> - struct irq_domain *domain, int irq)
> -{
> - void __iomem *base = domain->host_data;
> -
> - /* Disable and clear all interrupts */
> - __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
> - __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
> -
> - irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
> -}
> -
> -static int __init ath79_misc_intc_of_init(
> - struct device_node *node, struct device_node *parent)
> +static int ath79_misc_intc_probe(struct platform_device *pdev)
> {
> + struct device *dev = &pdev->dev;
> struct irq_domain *domain;
> void __iomem *base;
> int irq;
>
> - irq = irq_of_parse_and_map(node, 0);
> - if (!irq) {
> - pr_err("Failed to get MISC IRQ\n");
> - return -EINVAL;
> - }
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
>
> - base = of_iomap(node, 0);
> - if (!base) {
> - pr_err("Failed to get MISC IRQ registers\n");
> - return -ENOMEM;
> - }
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
>
> - domain = irq_domain_create_linear(of_fwnode_handle(node), ATH79_MISC_IRQ_COUNT,
> - &misc_irq_domain_ops, base);
> - if (!domain) {
> - pr_err("Failed to add MISC irqdomain\n");
> - return -EINVAL;
> - }
> + domain = devm_irq_domain_create_linear(dev, dev_fwnode(dev),
> + ATH79_MISC_IRQ_COUNT,
> + &misc_irq_domain_ops, base);
> + if (!domain)
> + return dev_err_probe(dev, -ENOMEM, "failed to add the irq domain\n");
> +
> + /* Disable and clear all interrupts */
> + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
> + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
>
> - ath79_misc_intc_domain_init(domain, irq);
> + irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
> ath79_misc_domain = domain;
> +
> return 0;
> }
>
> -static int __init ar7100_misc_intc_of_init(
> - struct device_node *node, struct device_node *parent)
> +static int ar7100_misc_intc_probe(struct platform_device *pdev,
> + struct device_node *parent)
> {
> ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
> - return ath79_misc_intc_of_init(node, parent);
> + return ath79_misc_intc_probe(pdev);
> }
>
> -IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
> - ar7100_misc_intc_of_init);
> -
> -static int __init ar7240_misc_intc_of_init(
> - struct device_node *node, struct device_node *parent)
> +static int ar7240_misc_intc_probe(struct platform_device *pdev,
> + struct device_node *parent)
> {
> ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
> - return ath79_misc_intc_of_init(node, parent);
> + return ath79_misc_intc_probe(pdev);
> }
>
> -IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
> - ar7240_misc_intc_of_init);
> +IRQCHIP_PLATFORM_DRIVER_BEGIN(ath79_misc_intc)
> +IRQCHIP_MATCH("qca,ar7100-misc-intc", ar7100_misc_intc_probe)
> +IRQCHIP_MATCH("qca,ar7240-misc-intc", ar7240_misc_intc_probe)
> +IRQCHIP_PLATFORM_DRIVER_END(ath79_misc_intc)
[Severity: High]
Does probing ath79_misc_intc at device_initcall time clobber
MISC_INT_MIPS_SI_TIMERINT_MASK in AR71XX_RESET_REG_MISC_INT_ENABLE on
QCA956x?
With IRQCHIP_DECLARE(), this driver ran during init_IRQ() before
time_init() -> plat_time_init() -> of_clk_init() called
qca956x_clocks_init():
arch/mips/ath79/clock.c:qca956x_clocks_init() {
...
/*
* QCA956x timer init workaround has to be applied right before setting
* up the clock. Else, there will be no jiffies
*/
u32 misc;
misc = ath79_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
ath79_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, misc);
...
}
Moving registration to IRQCHIP_PLATFORM_DRIVER_BEGIN() runs
ath79_misc_intc_probe() after time_init(), where the unconditional write of
0 to AR71XX_RESET_REG_MISC_INT_ENABLE clears MISC_INT_MIPS_SI_TIMERINT_MASK
and breaks the CPU timer interrupt on QCA956x, TP9343, and QCN550x SoCs.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112224445.213324-1-rosenp@gmail.com?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-11-12 23:00 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 22:44 [PATCH 0/4] irqchip/ath79-misc: probe as a platform driver Rosen Penev
2026-11-12 22:44 ` [PATCH 1/4] MIPS: perf: look up the PMU interrupt when it is requested Rosen Penev
2026-11-12 22:55 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 2/4] irqchip/ath79-misc: map the performance counter interrupt on demand Rosen Penev
2026-11-12 22:52 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 3/4] irqchip/ath79-misc: convert to a platform driver Rosen Penev
2026-11-12 23:00 ` sashiko-bot
2026-11-12 22:44 ` [PATCH 4/4] irqchip/ath79-misc: allow COMPILE_TEST builds Rosen Penev
2026-11-12 22:51 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.