Skip to contentSkip to conversation

genirq: Add support for percpu_devid IRQ affinity

PATCH Applied Marc Zyngier 4 participants 73 messages Oct 20, 2025 – Dec 5, 2025

Subsystems (13)
ACPI MIPS arm64 Driver core +9 more subsystems
lore
Share & tools
lore

Marc Zyngier

author maintainer
#0 lore raw

v4 cover genirq: Add support for percpu_devid IRQ affinity

This is the fourth version of this series, originally posted at [1], which aims at allowing percpu_devid interrupt requests on the basis of an affinity mask. See the original submission for the details of why this is a desirable outcome.

From v3, we have some additional tidying up, thanks to Jonathan's review, and a bunch of tags -- see changelog for details.

FWIW, I've pushed a branch at [0].

* From v3 [3]:

- Additional cleanups in of_irq_get_affinity() (Jonathan)

- Rebased on 6.18-rc2

- Collected Abs, Rbs and Tbs, with thanks (Raphael, Jonathan, Jinjie, Suzuki, Sven, Will)

* From v2 [2]:

- Turned of_node_to_fwnode() usage to of_fwnode_handle() (Jonathan)

- Added a patch to finally kill of_node_to_fwnode()

- Tidied-up documentation, comments and formatting (Jonathan)

- Collected ABs and Rbs, with thanks (Jonathan, Suzuki, Sven)

* From v1 [1]:

- Fixed NMI handling by getting rid of the NMI-specific flow handler, which was pretty useless anyway (Will)

- As a result, killed a metric buttload worth of GICv3 code

- Moved irq_fwspec out of irq_fwspec_info, and passed it as a parameter to irq_get_fwspec_info(), renamed from irq_get_info(), and applied some generous sanitisation of the structure (Thomas)

- Dropped the rather useless fwspec validity flag (Thomas)

- Rejigged the PMU per-CPU handling to better deal with the DT/ACPI differences, and drop some now useless patches (Will)

- Plenty of cosmetic rework (Raphael, Thomas)

[0] git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/ppi-affinity
[1] https://lore.kernel.org/r/[email protected]
[2] https://lore.kernel.org/r/[email protected]
[3] https://lore.kernel.org/r/[email protected]

Marc Zyngier (25):
irqdomain: Add firmware info reporting interface
ACPI: irq: Add IRQ affinity reporting interface
of/irq: Add IRQ affinity reporting interface
platform: Add firmware-agnostic irq and affinity retrieval interface irqchip/gic-v3: Add FW info retrieval support irqchip/apple-aic: Add FW info retrieval support
coresight: trbe: Convert to new IRQ affinity retrieval API
perf: arm_pmu: Convert to new IRQ affinity retrieval API
perf: arm_spe_pmu: Convert to new IRQ affinity retrieval API irqchip/gic-v3: Switch high priority PPIs over to
handle_percpu_devid_irq()
genirq: Kill handle_percpu_devid_fasteoi_nmi()
genirq: Merge irqaction::{dev_id,percpu_dev_id}
genirq: Factor-in percpu irqaction creation
genirq: Add affinity to percpu_devid interrupt requests
genirq: Update request_percpu_nmi() to take an affinity
genirq: Allow per-cpu interrupt sharing for non-overlapping affinities
genirq: Add request_percpu_irq_affinity() helper
perf: arm_spe_pmu: Request specific affinities for percpu IRQ
coresight: trbe: Request specific affinities for percpu IRQ irqchip/gic-v3: Drop support for custom PPI partitions irqchip/apple-aic: Drop support for custom PMU irq partitions
irqchip: Kill irq-partition-percpu
genirq: Kill irq_{g,s}et_percpu_devid_partition()
irqdomain: Kill of_node_to_fwnode() helper
perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer

Will Deacon (1):
perf: arm_pmu: Request specific affinities for percpu NMI/IRQ

 arch/arm64/kernel/smp.c                      |   2 +-
 drivers/acpi/irq.c                           |  19 ++
 drivers/base/platform.c                      |  60 ++++-
 drivers/hwtracing/coresight/coresight-trbe.c |   9 +-
 drivers/irqchip/Kconfig                      |   4 -
 drivers/irqchip/Makefile                     |   1 -
 drivers/irqchip/irq-apple-aic.c              |  56 +++--
 drivers/irqchip/irq-gic-v3.c                 | 224 +++++------------
 drivers/irqchip/irq-partition-percpu.c       | 241 -------------------
 drivers/of/irq.c                             |  20 ++
 drivers/perf/arm_pmu.c                       |  49 ++--
 drivers/perf/arm_pmu_acpi.c                  |   2 +-
 drivers/perf/arm_pmu_platform.c              |  20 +-
 drivers/perf/arm_pmuv3.c                     |   2 +-
 drivers/perf/arm_spe_pmu.c                   |  13 +-
 include/linux/acpi.h                         |   7 +
 include/linux/interrupt.h                    |  24 +-
 include/linux/irq.h                          |   5 -
 include/linux/irqchip/irq-partition-percpu.h |  53 ----
 include/linux/irqdesc.h                      |   1 -
 include/linux/irqdomain.h                    |  33 ++-
 include/linux/of_irq.h                       |   7 +
 include/linux/perf/arm_pmu.h                 |   6 +-
 include/linux/platform_device.h              |   2 +
 kernel/irq/chip.c                            |  33 +--
 kernel/irq/irqdesc.c                         |  24 +-
 kernel/irq/irqdomain.c                       |  32 ++-
 kernel/irq/manage.c                          | 125 +++++++---
 28 files changed, 419 insertions(+), 655 deletions(-)
 delete mode 100644 drivers/irqchip/irq-partition-percpu.c
 delete mode 100644 include/linux/irqchip/irq-partition-percpu.h
Signature · 1 line
2.47.3
author maintainer
#1 lore raw

PATCH v4 1/26 irqdomain: Add firmware info reporting interface

Allow an irqdomain callback to report firmware-provided information that is otherwise not available in a generic way. This is reported using a new data structure (struct irq_fwspec_info).

This callback is optional and the only information that can be reported currently is the affinity of an interrupt. However, the containing structure is designed to be extensible, allowing other potentially relevant information to be reported in the future.

---
 include/linux/irqdomain.h | 27 +++++++++++++++++++++++++++
 kernel/irq/irqdomain.c    | 32 +++++++++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 5 deletions(-)
include/linux/irqdomain.h +27 -0
index 4a86e6b915dd6..9d6a5e99394fa 100644
@@ -44,6 +44,23 @@ struct irq_fwspec {
 	u32			param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
 };
 
+/**
+ * struct irq_fwspec_info - firmware provided IRQ information structure
+ *
+ * @flags:		Information validity flags
+ * @cpumask:		Affinity mask for this interrupt
+ *
+ * This structure reports firmware-specific information about an
+ * interrupt. The only significant information is the affinity of a
+ * per-CPU interrupt, but this is designed to be extended as required.
+ */
+struct irq_fwspec_info {
+	unsigned long		flags;
+	const struct cpumask	*affinity;
+};
+
+#define IRQ_FWSPEC_INFO_AFFINITY_VALID	BIT(0)
+
 /* Conversion function from of_phandle_args fields to fwspec  */
 void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
 			       unsigned int count, struct irq_fwspec *fwspec);
@@ -69,6 +86,9 @@ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
  * @translate:	Given @fwspec, decode the hardware irq number (@out_hwirq) and
  *		linux irq type value (@out_type). This is a generalised @xlate
  *		(over struct irq_fwspec) and is preferred if provided.
+ * @get_fwspec_info:
+ *		Given @fwspec, report additional firmware-provided information in
+ *		@info. Optional.
  * @debug_show:	For domains to show specific data for an interrupt in debugfs.
  *
  * Functions below are provided by the driver and called whenever a new mapping
@@ -96,6 +116,7 @@ struct irq_domain_ops {
 	void	(*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
 	int	(*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
 			     unsigned long *out_hwirq, unsigned int *out_type);
+	int	(*get_fwspec_info)(struct irq_fwspec *fwspec, struct irq_fwspec_info *info);
 #endif
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
 	void	(*debug_show)(struct seq_file *m, struct irq_domain *d,
@@ -602,6 +623,8 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain, unsigned int irq_bas
 
 int irq_domain_disconnect_hierarchy(struct irq_domain *domain, unsigned int virq);
 
+int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info);
+
 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
@@ -685,6 +708,10 @@ static inline bool irq_domain_is_msi_device(struct irq_domain *domain)
 	return false;
 }
 
+static inline int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	return -EINVAL;
+}
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #ifdef CONFIG_GENERIC_MSI_IRQ
kernel/irq/irqdomain.c +27 -5
index dc473faadcc81..2652c4cfd877f 100644
@@ -867,13 +867,9 @@ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
 }
 EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec);
 
-unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+static struct irq_domain *fwspec_to_domain(struct irq_fwspec *fwspec)
 {
 	struct irq_domain *domain;
-	struct irq_data *irq_data;
-	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	int virq;
 
 	if (fwspec->fwnode) {
 		domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
@@ -883,6 +879,32 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 		domain = irq_default_domain;
 	}
 
+	return domain;
+}
+
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	struct irq_domain *domain = fwspec_to_domain(fwspec);
+
+	memset(info, 0, sizeof(*info));
+
+	if (!domain || !domain->ops->get_fwspec_info)
+		return 0;
+
+	return domain->ops->get_fwspec_info(fwspec, info);
+}
+#endif
+
+unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+{
+	unsigned int type = IRQ_TYPE_NONE;
+	struct irq_domain *domain;
+	struct irq_data *irq_data;
+	irq_hw_number_t hwirq;
+	int virq;
+
+	domain = fwspec_to_domain(fwspec);
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
 			of_node_full_name(to_of_node(fwspec->fwnode)));
Signature · 1 line
2.47.3
merge bot Applied
#2 lore raw

[tip: irq/core] irqdomain: Add firmware info reporting interface

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     87b0031f7f73dac2ebb874fc8f331a66ee3b5cbd
Gitweb:        https://git.kernel.org/tip/87b0031f7f73dac2ebb874fc8f331a66ee3b5cbd
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:18 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:32 +01:00

irqdomain: Add firmware info reporting interface

Add an irqdomain callback to report firmware-provided information that is otherwise not available in a generic way. This is reported using a new data structure (struct irq_fwspec_info).

This callback is optional and the only information that can be reported currently is the affinity of an interrupt. However, the containing structure is designed to be extensible, allowing other potentially relevant information to be reported in the future.

---
 include/linux/irqdomain.h | 27 +++++++++++++++++++++++++++
 kernel/irq/irqdomain.c    | 32 +++++++++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 5 deletions(-)
include/linux/irqdomain.h +27 -0
index 4a86e6b..9d6a5e9 100644
@@ -44,6 +44,23 @@ struct irq_fwspec {
 	u32			param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
 };
 
+/**
+ * struct irq_fwspec_info - firmware provided IRQ information structure
+ *
+ * @flags:		Information validity flags
+ * @cpumask:		Affinity mask for this interrupt
+ *
+ * This structure reports firmware-specific information about an
+ * interrupt. The only significant information is the affinity of a
+ * per-CPU interrupt, but this is designed to be extended as required.
+ */
+struct irq_fwspec_info {
+	unsigned long		flags;
+	const struct cpumask	*affinity;
+};
+
+#define IRQ_FWSPEC_INFO_AFFINITY_VALID	BIT(0)
+
 /* Conversion function from of_phandle_args fields to fwspec  */
 void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
 			       unsigned int count, struct irq_fwspec *fwspec);
@@ -69,6 +86,9 @@ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
  * @translate:	Given @fwspec, decode the hardware irq number (@out_hwirq) and
  *		linux irq type value (@out_type). This is a generalised @xlate
  *		(over struct irq_fwspec) and is preferred if provided.
+ * @get_fwspec_info:
+ *		Given @fwspec, report additional firmware-provided information in
+ *		@info. Optional.
  * @debug_show:	For domains to show specific data for an interrupt in debugfs.
  *
  * Functions below are provided by the driver and called whenever a new mapping
@@ -96,6 +116,7 @@ struct irq_domain_ops {
 	void	(*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
 	int	(*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
 			     unsigned long *out_hwirq, unsigned int *out_type);
+	int	(*get_fwspec_info)(struct irq_fwspec *fwspec, struct irq_fwspec_info *info);
 #endif
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
 	void	(*debug_show)(struct seq_file *m, struct irq_domain *d,
@@ -602,6 +623,8 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain, unsigned int irq_bas
 
 int irq_domain_disconnect_hierarchy(struct irq_domain *domain, unsigned int virq);
 
+int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info);
+
 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
@@ -685,6 +708,10 @@ static inline bool irq_domain_is_msi_device(struct irq_domain *domain)
 	return false;
 }
 
+static inline int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	return -EINVAL;
+}
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #ifdef CONFIG_GENERIC_MSI_IRQ
kernel/irq/irqdomain.c +27 -5
index dc473fa..2652c4c 100644
@@ -867,13 +867,9 @@ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
 }
 EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec);
 
-unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+static struct irq_domain *fwspec_to_domain(struct irq_fwspec *fwspec)
 {
 	struct irq_domain *domain;
-	struct irq_data *irq_data;
-	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	int virq;
 
 	if (fwspec->fwnode) {
 		domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
@@ -883,6 +879,32 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 		domain = irq_default_domain;
 	}
 
+	return domain;
+}
+
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	struct irq_domain *domain = fwspec_to_domain(fwspec);
+
+	memset(info, 0, sizeof(*info));
+
+	if (!domain || !domain->ops->get_fwspec_info)
+		return 0;
+
+	return domain->ops->get_fwspec_info(fwspec, info);
+}
+#endif
+
+unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+{
+	unsigned int type = IRQ_TYPE_NONE;
+	struct irq_domain *domain;
+	struct irq_data *irq_data;
+	irq_hw_number_t hwirq;
+	int virq;
+
+	domain = fwspec_to_domain(fwspec);
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
 			of_node_full_name(to_of_node(fwspec->fwnode)));
author maintainer
#3 lore raw

PATCH v4 2/26 ACPI: irq: Add IRQ affinity reporting interface

In reply to Marc Zyngier

Plug the irq_populate_fwspec_info() helper into the ACPI layer to offer an IRQ affinity reporting function. This is currently only supported for the CONFIG_ACPI_GENERIC_GSI configurations, but could later be extended to legacy architectures if necessary.

---
 drivers/acpi/irq.c   | 19 +++++++++++++++++++
 include/linux/acpi.h |  7 +++++++
 2 files changed, 26 insertions(+)
drivers/acpi/irq.c +19 -0
index 76a856c32c4d0..d1595156c86a4 100644
@@ -300,6 +300,25 @@ int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
 }
 EXPORT_SYMBOL_GPL(acpi_irq_get);
 
+const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+					    unsigned int index)
+{
+	struct irq_fwspec_info info;
+	struct irq_fwspec fwspec;
+	unsigned long flags;
+
+	if (acpi_irq_parse_one(handle, index, &fwspec, &flags))
+		return NULL;
+
+	if (irq_populate_fwspec_info(&fwspec, &info))
+		return NULL;
+
+	if (!(info.flags & IRQ_FWSPEC_INFO_AFFINITY_VALID))
+		return NULL;
+
+	return info.affinity;
+}
+
 /**
  * acpi_set_irq_model - Setup the GSI irqdomain information
  * @model: the value assigned to acpi_irq_model
include/linux/acpi.h +7 -0
index 5ff5d99f6ead5..607db773b6721 100644
@@ -1509,12 +1509,19 @@ static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console)
 
 #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res);
+const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+					    unsigned int index);
 #else
 static inline
 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
 {
 	return -EINVAL;
 }
+static inline const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+							  unsigned int index)
+{
+	return NULL;
+}
 #endif
 
 #ifdef CONFIG_ACPI_LPIT
Signature · 1 line
2.47.3
merge bot Applied
#4 lore raw

[tip: irq/core] ACPI: irq: Add interrupt affinity reporting interface

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     5324fe21ba9b77b299c02191645a97777cdd73ac
Gitweb:        https://git.kernel.org/tip/5324fe21ba9b77b299c02191645a97777cdd73ac
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:19 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:32 +01:00

ACPI: irq: Add interrupt affinity reporting interface

Plug the irq_populate_fwspec_info() helper into the ACPI layer to offer an interrupt affinity reporting function. This is currently only supported for the CONFIG_ACPI_GENERIC_GSI configurations, but could later be extended to legacy architectures if necessary.

---
 drivers/acpi/irq.c   | 19 +++++++++++++++++++
 include/linux/acpi.h |  7 +++++++
 2 files changed, 26 insertions(+)
drivers/acpi/irq.c +19 -0
index 76a856c..d159515 100644
@@ -300,6 +300,25 @@ int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
 }
 EXPORT_SYMBOL_GPL(acpi_irq_get);
 
+const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+					    unsigned int index)
+{
+	struct irq_fwspec_info info;
+	struct irq_fwspec fwspec;
+	unsigned long flags;
+
+	if (acpi_irq_parse_one(handle, index, &fwspec, &flags))
+		return NULL;
+
+	if (irq_populate_fwspec_info(&fwspec, &info))
+		return NULL;
+
+	if (!(info.flags & IRQ_FWSPEC_INFO_AFFINITY_VALID))
+		return NULL;
+
+	return info.affinity;
+}
+
 /**
  * acpi_set_irq_model - Setup the GSI irqdomain information
  * @model: the value assigned to acpi_irq_model
include/linux/acpi.h +7 -0
index 5ff5d99..607db77 100644
@@ -1509,12 +1509,19 @@ static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console)
 
 #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res);
+const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+					    unsigned int index);
 #else
 static inline
 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
 {
 	return -EINVAL;
 }
+static inline const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
+							  unsigned int index)
+{
+	return NULL;
+}
 #endif
 
 #ifdef CONFIG_ACPI_LPIT
author maintainer
#5 lore raw

PATCH v4 3/26 of/irq: Add IRQ affinity reporting interface

In reply to Marc Zyngier

Plug the irq_populate_fwspec_info() helper into the OF layer to offer an IRQ affinity reporting function.

---
 drivers/of/irq.c       | 20 ++++++++++++++++++++
 include/linux/of_irq.h |  7 +++++++
 2 files changed, 27 insertions(+)
drivers/of/irq.c +20 -0
index 65c3c23255b74..168fde921bd27 100644
@@ -479,6 +479,26 @@ int of_irq_get(struct device_node *dev, int index)
 }
 EXPORT_SYMBOL_GPL(of_irq_get);
 
+const struct cpumask *of_irq_get_affinity(struct device_node *dev, int index)
+{
+	struct of_phandle_args oirq;
+	struct irq_fwspec_info info;
+	struct irq_fwspec fwspec;
+	int rc;
+
+	rc = of_irq_parse_one(dev, index, &oirq);
+	if (rc)
+		return NULL;
+
+	of_phandle_args_to_fwspec(oirq.np, oirq.args, oirq.args_count,
+				  &fwspec);
+
+	if (irq_populate_fwspec_info(&fwspec, &info))
+		return NULL;
+
+	return info.affinity;
+}
+
 /**
  * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
include/linux/of_irq.h +7 -0
index 1db8543dfc8a6..1c2bc02818071 100644
@@ -43,6 +43,8 @@ extern int of_irq_parse_one(struct device_node *device, int index,
 			  struct of_phandle_args *out_irq);
 extern int of_irq_count(struct device_node *dev);
 extern int of_irq_get(struct device_node *dev, int index);
+extern const struct cpumask *of_irq_get_affinity(struct device_node *dev,
+						      int index);
 extern int of_irq_get_byname(struct device_node *dev, const char *name);
 extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
@@ -76,6 +78,11 @@ static inline int of_irq_get_byname(struct device_node *dev, const char *name)
 {
 	return 0;
 }
+static inline const struct cpumask *of_irq_get_affinity(struct device_node *dev,
+							int index)
+{
+	return NULL;
+}
 static inline int of_irq_to_resource_table(struct device_node *dev,
 					   struct resource *res, int nr_irqs)
 {
Signature · 1 line
2.47.3
merge bot Applied
#6 lore raw

[tip: irq/core] of/irq: Add interrupt affinity reporting interface

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     5404f5c06dd41fd4445a01dec77a629e254a62e8
Gitweb:        https://git.kernel.org/tip/5404f5c06dd41fd4445a01dec77a629e254a62e8
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:20 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:32 +01:00

of/irq: Add interrupt affinity reporting interface

Plug the irq_populate_fwspec_info() helper into the OF layer to offer an interrupt affinity reporting function.

---
 drivers/of/irq.c       | 20 ++++++++++++++++++++
 include/linux/of_irq.h |  7 +++++++
 2 files changed, 27 insertions(+)
drivers/of/irq.c +20 -0
index 65c3c23..168fde9 100644
@@ -479,6 +479,26 @@ out:
 }
 EXPORT_SYMBOL_GPL(of_irq_get);
 
+const struct cpumask *of_irq_get_affinity(struct device_node *dev, int index)
+{
+	struct of_phandle_args oirq;
+	struct irq_fwspec_info info;
+	struct irq_fwspec fwspec;
+	int rc;
+
+	rc = of_irq_parse_one(dev, index, &oirq);
+	if (rc)
+		return NULL;
+
+	of_phandle_args_to_fwspec(oirq.np, oirq.args, oirq.args_count,
+				  &fwspec);
+
+	if (irq_populate_fwspec_info(&fwspec, &info))
+		return NULL;
+
+	return info.affinity;
+}
+
 /**
  * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
include/linux/of_irq.h +7 -0
index 1db8543..1c2bc02 100644
@@ -43,6 +43,8 @@ extern int of_irq_parse_one(struct device_node *device, int index,
 			  struct of_phandle_args *out_irq);
 extern int of_irq_count(struct device_node *dev);
 extern int of_irq_get(struct device_node *dev, int index);
+extern const struct cpumask *of_irq_get_affinity(struct device_node *dev,
+						      int index);
 extern int of_irq_get_byname(struct device_node *dev, const char *name);
 extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
@@ -76,6 +78,11 @@ static inline int of_irq_get_byname(struct device_node *dev, const char *name)
 {
 	return 0;
 }
+static inline const struct cpumask *of_irq_get_affinity(struct device_node *dev,
+							int index)
+{
+	return NULL;
+}
 static inline int of_irq_to_resource_table(struct device_node *dev,
 					   struct resource *res, int nr_irqs)
 {
author maintainer
#7 lore raw

PATCH v4 4/26 platform: Add firmware-agnostic irq and affinity retrieval interface

In reply to Marc Zyngier

Expand platform_get_irq_optional() to also return an affinity if available, renaming it to platform_get_irq_affinity() in the process.

platform_get_irq_optional() is preserved with its current semantics by calling into the new helper with a NULL affinity pointer.

---
 drivers/base/platform.c         | 60 +++++++++++++++++++++++++++------
 include/linux/platform_device.h |  2 ++
 2 files changed, 52 insertions(+), 10 deletions(-)
drivers/base/platform.c +50 -10
index 09450349cf323..3a058f63ef0d3 100644
@@ -150,25 +150,37 @@ devm_platform_ioremap_resource_byname(struct platform_device *pdev,
 EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname);
 #endif /* CONFIG_HAS_IOMEM */
 
+static const struct cpumask *get_irq_affinity(struct platform_device *dev,
+					      unsigned int num)
+{
+	const struct cpumask *mask = NULL;
+#ifndef CONFIG_SPARC
+	struct fwnode_handle *fwnode = dev_fwnode(&dev->dev);
+
+	if (is_of_node(fwnode))
+		mask = of_irq_get_affinity(to_of_node(fwnode), num);
+	else if (is_acpi_device_node(fwnode))
+		mask = acpi_irq_get_affinity(ACPI_HANDLE_FWNODE(fwnode), num);
+#endif
+
+	return mask ?: cpu_possible_mask;
+}
+
 /**
- * platform_get_irq_optional - get an optional IRQ for a device
+ * platform_get_irq_affinity - get an optional IRQ and its affinity for a device
  * @dev: platform device
  * @num: IRQ number index
+ * @affinity: optional cpumask pointer to get the affinity of a per-cpu IRQ
  *
  * Gets an IRQ for a platform device. Device drivers should check the return
  * value for errors so as to not pass a negative integer value to the
- * request_irq() APIs. This is the same as platform_get_irq(), except that it
- * does not print an error message if an IRQ can not be obtained.
- *
- * For example::
- *
- *		int irq = platform_get_irq_optional(pdev, 0);
- *		if (irq < 0)
- *			return irq;
+ * request_irq() APIs. Optional affinity information is provided in the
+ * affinity pointer if available, and NULL otherwise.
  *
  * Return: non-zero IRQ number on success, negative error number on failure.
  */
-int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
+int platform_get_irq_affinity(struct platform_device *dev, unsigned int num,
+			      const struct cpumask **affinity)
 {
 	int ret;
 #ifdef CONFIG_SPARC
@@ -236,8 +248,36 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
 out:
 	if (WARN(!ret, "0 is an invalid IRQ number\n"))
 		return -EINVAL;
+
+	if (ret > 0 && affinity)
+		*affinity = get_irq_affinity(dev, num);
+
 	return ret;
 }
+EXPORT_SYMBOL_GPL(platform_get_irq_affinity);
+
+/**
+ * platform_get_irq_optional - get an optional IRQ for a device
+ * @dev: platform device
+ * @num: IRQ number index
+ *
+ * Gets an IRQ for a platform device. Device drivers should check the return
+ * value for errors so as to not pass a negative integer value to the
+ * request_irq() APIs. This is the same as platform_get_irq(), except that it
+ * does not print an error message if an IRQ can not be obtained.
+ *
+ * For example::
+ *
+ *		int irq = platform_get_irq_optional(pdev, 0);
+ *		if (irq < 0)
+ *			return irq;
+ *
+ * Return: non-zero IRQ number on success, negative error number on failure.
+ */
+int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
+{
+	return platform_get_irq_affinity(dev, num, NULL);
+}
 EXPORT_SYMBOL_GPL(platform_get_irq_optional);
 
 /**
include/linux/platform_device.h +2 -0
index 074754c23d330..ad66333ce85ce 100644
@@ -102,6 +102,8 @@ devm_platform_ioremap_resource_byname(struct platform_device *pdev,
 
 extern int platform_get_irq(struct platform_device *, unsigned int);
 extern int platform_get_irq_optional(struct platform_device *, unsigned int);
+extern int platform_get_irq_affinity(struct platform_device *, unsigned int,
+				     const struct cpumask **);
 extern int platform_irq_count(struct platform_device *);
 extern int devm_platform_get_irqs_affinity(struct platform_device *dev,
 					   struct irq_affinity *affd,
Signature · 1 line
2.47.3
merge bot Applied
#8 lore raw

[tip: irq/core] platform: Add firmware-agnostic irq and affinity retrieval interface

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     0d5daa938c94b8b9183e9b257a88dc0929d59409
Gitweb:        https://git.kernel.org/tip/0d5daa938c94b8b9183e9b257a88dc0929d59409
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:21 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:32 +01:00

platform: Add firmware-agnostic irq and affinity retrieval interface

Expand platform_get_irq_optional() to also return an affinity if available, renaming it to platform_get_irq_affinity() in the process.

platform_get_irq_optional() is preserved with its current semantics by calling into the new helper with a NULL affinity pointer.

---
 drivers/base/platform.c         | 71 +++++++++++++++++++++++++-------
 include/linux/platform_device.h |  2 +-
 2 files changed, 58 insertions(+), 15 deletions(-)
drivers/base/platform.c +56 -15
index 0945034..b45d41b 100644
@@ -150,25 +150,37 @@ devm_platform_ioremap_resource_byname(struct platform_device *pdev,
 EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname);
 #endif /* CONFIG_HAS_IOMEM */
 
+static const struct cpumask *get_irq_affinity(struct platform_device *dev,
+					      unsigned int num)
+{
+	const struct cpumask *mask = NULL;
+#ifndef CONFIG_SPARC
+	struct fwnode_handle *fwnode = dev_fwnode(&dev->dev);
+
+	if (is_of_node(fwnode))
+		mask = of_irq_get_affinity(to_of_node(fwnode), num);
+	else if (is_acpi_device_node(fwnode))
+		mask = acpi_irq_get_affinity(ACPI_HANDLE_FWNODE(fwnode), num);
+#endif
+
+	return mask ?: cpu_possible_mask;
+}
+
 /**
- * platform_get_irq_optional - get an optional IRQ for a device
- * @dev: platform device
- * @num: IRQ number index
+ * platform_get_irq_affinity - get an optional IRQ and its affinity for a device
+ * @dev:	platform device
+ * @num:	interrupt number index
+ * @affinity:	optional cpumask pointer to get the affinity of a per-cpu interrupt
  *
- * Gets an IRQ for a platform device. Device drivers should check the return
- * value for errors so as to not pass a negative integer value to the
- * request_irq() APIs. This is the same as platform_get_irq(), except that it
- * does not print an error message if an IRQ can not be obtained.
- *
- * For example::
- *
- *		int irq = platform_get_irq_optional(pdev, 0);
- *		if (irq < 0)
- *			return irq;
+ * Gets an interupt for a platform device. Device drivers should check the
+ * return value for errors so as to not pass a negative integer value to
+ * the request_irq() APIs. Optional affinity information is provided in the
+ * affinity pointer if available, and NULL otherwise.
  *
- * Return: non-zero IRQ number on success, negative error number on failure.
+ * Return: non-zero interrupt number on success, negative error number on failure.
  */
-int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
+int platform_get_irq_affinity(struct platform_device *dev, unsigned int num,
+			      const struct cpumask **affinity)
 {
 	int ret;
 #ifdef CONFIG_SPARC
@@ -236,8 +248,37 @@ out_not_found:
 out:
 	if (WARN(!ret, "0 is an invalid IRQ number\n"))
 		return -EINVAL;
+
+	if (ret > 0 && affinity)
+		*affinity = get_irq_affinity(dev, num);
+
 	return ret;
 }
+EXPORT_SYMBOL_GPL(platform_get_irq_affinity);
+
+/**
+ * platform_get_irq_optional - get an optional interrupt for a device
+ * @dev:	platform device
+ * @num:	interrupt number index
+ *
+ * Gets an interrupt for a platform device. Device drivers should check the
+ * return value for errors so as to not pass a negative integer value to
+ * the request_irq() APIs. This is the same as platform_get_irq(), except
+ * that it does not print an error message if an interrupt can not be
+ * obtained.
+ *
+ * For example::
+ *
+ *		int irq = platform_get_irq_optional(pdev, 0);
+ *		if (irq < 0)
+ *			return irq;
+ *
+ * Return: non-zero interrupt number on success, negative error number on failure.
+ */
+int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
+{
+	return platform_get_irq_affinity(dev, num, NULL);
+}
 EXPORT_SYMBOL_GPL(platform_get_irq_optional);
 
 /**
include/linux/platform_device.h +2 -0
index 074754c..ad66333 100644
@@ -102,6 +102,8 @@ devm_platform_ioremap_resource_byname(struct platform_device *pdev,
 
 extern int platform_get_irq(struct platform_device *, unsigned int);
 extern int platform_get_irq_optional(struct platform_device *, unsigned int);
+extern int platform_get_irq_affinity(struct platform_device *, unsigned int,
+				     const struct cpumask **);
 extern int platform_irq_count(struct platform_device *);
 extern int devm_platform_get_irqs_affinity(struct platform_device *dev,
 					   struct irq_affinity *affd,
author maintainer
#9 lore raw

PATCH v4 5/26 irqchip/gic-v3: Add FW info retrieval support

In reply to Marc Zyngier

Plug the new .get_fwspec_info() callback into the GICv3 core driver, using some of the existing PPI affinity handling infrastructure.

---
 drivers/irqchip/irq-gic-v3.c | 53 ++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
drivers/irqchip/irq-gic-v3.c +53 -0
index 3de351e66ee84..cf0ba83c6eda6 100644
@@ -69,6 +69,8 @@ struct gic_chip_data {
 	bool			has_rss;
 	unsigned int		ppi_nr;
 	struct partition_desc	**ppi_descs;
+	struct partition_affinity *parts;
+	unsigned int		nr_parts;
 };
 
 #define T241_CHIPS_MAX		4
@@ -1797,11 +1799,58 @@ static int gic_irq_domain_select(struct irq_domain *d,
 	return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
 }
 
+static int gic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	const struct cpumask *mask = NULL;
+
+	info->flags = 0;
+	info->affinity = NULL;
+
+	/* ACPI is not capable of describing PPI affinity -- yet */
+	if (!is_of_node(fwspec->fwnode))
+		return 0;
+
+	/* If the specifier provides an affinity, use it */
+	if (fwspec->param_count == 4 && fwspec->param[3]) {
+		struct fwnode_handle *fw;
+
+		switch (fwspec->param[0]) {
+		case 1:			/* PPI */
+		case 3:			/* EPPI */
+			break;
+		default:
+			return 0;
+		}
+
+		fw = of_fwnode_handle(of_find_node_by_phandle(fwspec->param[3]));
+		if (!fw)
+			return -ENOENT;
+
+		for (int i = 0; i < gic_data.nr_parts; i++) {
+			if (gic_data.parts[i].partition_id == fw) {
+				mask = &gic_data.parts[i].mask;
+				break;
+			}
+		}
+
+		if (!mask)
+			return -ENOENT;
+	} else {
+		mask = cpu_possible_mask;
+	}
+
+	info->affinity = mask;
+	info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
+
+	return 0;
+}
+
 static const struct irq_domain_ops gic_irq_domain_ops = {
 	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = gic_irq_domain_free,
 	.select = gic_irq_domain_select,
+	.get_fwspec_info = gic_irq_get_fwspec_info,
 };
 
 static int partition_domain_translate(struct irq_domain *d,
@@ -1840,6 +1889,7 @@ static int partition_domain_translate(struct irq_domain *d,
 static const struct irq_domain_ops partition_domain_ops = {
 	.translate = partition_domain_translate,
 	.select = gic_irq_domain_select,
+	.get_fwspec_info = gic_irq_get_fwspec_info,
 };
 
 static bool gic_enable_quirk_msm8996(void *data)
@@ -2232,6 +2282,9 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 		part_idx++;
 	}
 
+	gic_data.parts = parts;
+	gic_data.nr_parts = nr_parts;
+
 	for (i = 0; i < gic_data.ppi_nr; i++) {
 		unsigned int irq;
 		struct partition_desc *desc;
Signature · 1 line
2.47.3
merge bot Applied
#10 lore raw

[tip: irq/core] irqchip/gic-v3: Add FW info retrieval support

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     68905ea65ceff4f42ab14dbc6882de313127646f
Gitweb:        https://git.kernel.org/tip/68905ea65ceff4f42ab14dbc6882de313127646f
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:22 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:33 +01:00

irqchip/gic-v3: Add FW info retrieval support

Plug the new .get_fwspec_info() callback into the GICv3 core driver, using some of the existing PPI affinity handling infrastructure.

---
 drivers/irqchip/irq-gic-v3.c | 53 +++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+)
drivers/irqchip/irq-gic-v3.c +53 -0
index 3de351e..cf0ba83 100644
@@ -69,6 +69,8 @@ struct gic_chip_data {
 	bool			has_rss;
 	unsigned int		ppi_nr;
 	struct partition_desc	**ppi_descs;
+	struct partition_affinity *parts;
+	unsigned int		nr_parts;
 };
 
 #define T241_CHIPS_MAX		4
@@ -1797,11 +1799,58 @@ static int gic_irq_domain_select(struct irq_domain *d,
 	return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
 }
 
+static int gic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	const struct cpumask *mask = NULL;
+
+	info->flags = 0;
+	info->affinity = NULL;
+
+	/* ACPI is not capable of describing PPI affinity -- yet */
+	if (!is_of_node(fwspec->fwnode))
+		return 0;
+
+	/* If the specifier provides an affinity, use it */
+	if (fwspec->param_count == 4 && fwspec->param[3]) {
+		struct fwnode_handle *fw;
+
+		switch (fwspec->param[0]) {
+		case 1:			/* PPI */
+		case 3:			/* EPPI */
+			break;
+		default:
+			return 0;
+		}
+
+		fw = of_fwnode_handle(of_find_node_by_phandle(fwspec->param[3]));
+		if (!fw)
+			return -ENOENT;
+
+		for (int i = 0; i < gic_data.nr_parts; i++) {
+			if (gic_data.parts[i].partition_id == fw) {
+				mask = &gic_data.parts[i].mask;
+				break;
+			}
+		}
+
+		if (!mask)
+			return -ENOENT;
+	} else {
+		mask = cpu_possible_mask;
+	}
+
+	info->affinity = mask;
+	info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
+
+	return 0;
+}
+
 static const struct irq_domain_ops gic_irq_domain_ops = {
 	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = gic_irq_domain_free,
 	.select = gic_irq_domain_select,
+	.get_fwspec_info = gic_irq_get_fwspec_info,
 };
 
 static int partition_domain_translate(struct irq_domain *d,
@@ -1840,6 +1889,7 @@ static int partition_domain_translate(struct irq_domain *d,
 static const struct irq_domain_ops partition_domain_ops = {
 	.translate = partition_domain_translate,
 	.select = gic_irq_domain_select,
+	.get_fwspec_info = gic_irq_get_fwspec_info,
 };
 
 static bool gic_enable_quirk_msm8996(void *data)
@@ -2232,6 +2282,9 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 		part_idx++;
 	}
 
+	gic_data.parts = parts;
+	gic_data.nr_parts = nr_parts;
+
 	for (i = 0; i < gic_data.ppi_nr; i++) {
 		unsigned int irq;
 		struct partition_desc *desc;
Reviewed-by on v4 5/26
#11 lore raw

Re: [PATCH v4 05/26] irqchip/gic-v3: Add FW info retrieval support

In reply to Marc Zyngier
Quoted 5 lines · On Mon, 20 Oct 2025 13:29:22 +0100 Marc Zyngier <[email protected]> wrote:

Plug the new .get_fwspec_info() callback into the GICv3 core driver, using some of the existing PPI affinity handling infrastructure.

author maintainer
#12 lore raw

PATCH v4 6/26 irqchip/apple-aic: Add FW info retrieval support

In reply to Marc Zyngier

Plug the new .get_fwspec_info() callback into the Apple AIC driver, using some of the existing FIQ affinity handling infrastructure.

---
 drivers/irqchip/irq-apple-aic.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
drivers/irqchip/irq-apple-aic.c +28 -0
index 032d66dceb8ec..cb8b6f40ce8d3 100644
@@ -651,6 +651,33 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
 	return 0;
 }
 
+static int aic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	const struct cpumask *mask;
+	u32 intid;
+
+	info->flags = 0;
+	info->affinity = NULL;
+
+	if (fwspec->param[0] != AIC_FIQ)
+		return 0;
+
+	if (fwspec->param_count == 3)
+		intid = fwspec->param[1];
+	else
+		intid = fwspec->param[2];
+
+	if (aic_irqc->fiq_aff[intid])
+		mask = &aic_irqc->fiq_aff[intid]->aff;
+	else
+		mask = cpu_possible_mask;
+
+	info->affinity = mask;
+	info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
+
+	return 0;
+}
+
 static int aic_irq_domain_translate(struct irq_domain *id,
 				    struct irq_fwspec *fwspec,
 				    unsigned long *hwirq,
@@ -753,6 +780,7 @@ static const struct irq_domain_ops aic_irq_domain_ops = {
 	.translate	= aic_irq_domain_translate,
 	.alloc		= aic_irq_domain_alloc,
 	.free		= aic_irq_domain_free,
+	.get_fwspec_info = aic_irq_get_fwspec_info,
 };
 
 /*
Signature · 1 line
2.47.3
merge bot Applied
#13 lore raw

[tip: irq/core] irqchip/apple-aic: Add FW info retrieval support

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     de575de83c77b693667256774f4d19f33e73f6db
Gitweb:        https://git.kernel.org/tip/de575de83c77b693667256774f4d19f33e73f6db
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:23 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:33 +01:00

irqchip/apple-aic: Add FW info retrieval support

Plug the new .get_fwspec_info() callback into the Apple AIC driver, using some of the existing FIQ affinity handling infrastructure.

---
 drivers/irqchip/irq-apple-aic.c | 34 +++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)
drivers/irqchip/irq-apple-aic.c +31 -3
index 032d66d..0b72451 100644
@@ -651,6 +651,33 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
 	return 0;
 }
 
+static int aic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+	const struct cpumask *mask;
+	u32 intid;
+
+	info->flags = 0;
+	info->affinity = NULL;
+
+	if (fwspec->param[0] != AIC_FIQ)
+		return 0;
+
+	if (fwspec->param_count == 3)
+		intid = fwspec->param[1];
+	else
+		intid = fwspec->param[2];
+
+	if (aic_irqc->fiq_aff[intid])
+		mask = &aic_irqc->fiq_aff[intid]->aff;
+	else
+		mask = cpu_possible_mask;
+
+	info->affinity = mask;
+	info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
+
+	return 0;
+}
+
 static int aic_irq_domain_translate(struct irq_domain *id,
 				    struct irq_fwspec *fwspec,
 				    unsigned long *hwirq,
@@ -750,9 +777,10 @@ static void aic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops aic_irq_domain_ops = {
-	.translate	= aic_irq_domain_translate,
-	.alloc		= aic_irq_domain_alloc,
-	.free		= aic_irq_domain_free,
+	.translate		= aic_irq_domain_translate,
+	.alloc			= aic_irq_domain_alloc,
+	.free			= aic_irq_domain_free,
+	.get_fwspec_info	= aic_irq_get_fwspec_info,
 };
 
 /*
author maintainer
#14 lore raw

PATCH v4 7/26 coresight: trbe: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the TRBE driver over to this new method.

---
 drivers/hwtracing/coresight/coresight-trbe.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/hwtracing/coresight/coresight-trbe.c +3 -3
index 43643d2c5bdd0..8f17160fec442 100644
@@ -1474,9 +1474,10 @@ static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata)
 static int arm_trbe_probe_irq(struct platform_device *pdev,
 			      struct trbe_drvdata *drvdata)
 {
+	const struct cpumask *affinity;
 	int ret;
 
-	drvdata->irq = platform_get_irq(pdev, 0);
+	drvdata->irq = platform_get_irq_affinity(pdev, 0, &affinity);
 	if (drvdata->irq < 0) {
 		pr_err("IRQ not found for the platform device\n");
 		return drvdata->irq;
@@ -1487,8 +1488,7 @@ static int arm_trbe_probe_irq(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
-	if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus))
-		return -EINVAL;
+	cpumask_copy(&drvdata->supported_cpus, affinity);
 
 	drvdata->handle = alloc_percpu(struct perf_output_handle *);
 	if (!drvdata->handle)
Signature · 1 line
2.47.3
merge bot Applied
#15 lore raw

[tip: irq/core] coresight: trbe: Convert to the new interrupt affinity retrieval API

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     541454dd204b66c9f03761e00a28ad9702b24829
Gitweb:        https://git.kernel.org/tip/541454dd204b66c9f03761e00a28ad9702b24829
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:24 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:33 +01:00

coresight: trbe: Convert to the new interrupt affinity retrieval API

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the TRBE driver over to this new method.

---
 drivers/hwtracing/coresight/coresight-trbe.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/hwtracing/coresight/coresight-trbe.c +3 -3
index 43643d2..8f17160 100644
@@ -1474,9 +1474,10 @@ static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata)
 static int arm_trbe_probe_irq(struct platform_device *pdev,
 			      struct trbe_drvdata *drvdata)
 {
+	const struct cpumask *affinity;
 	int ret;
 
-	drvdata->irq = platform_get_irq(pdev, 0);
+	drvdata->irq = platform_get_irq_affinity(pdev, 0, &affinity);
 	if (drvdata->irq < 0) {
 		pr_err("IRQ not found for the platform device\n");
 		return drvdata->irq;
@@ -1487,8 +1488,7 @@ static int arm_trbe_probe_irq(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
-	if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus))
-		return -EINVAL;
+	cpumask_copy(&drvdata->supported_cpus, affinity);
 
 	drvdata->handle = alloc_percpu(struct perf_output_handle *);
 	if (!drvdata->handle)
Reviewed-by on v4 7/26
#16 lore raw

Re: [PATCH v4 07/26] coresight: trbe: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier
Quoted 7 lines · On Mon, 20 Oct 2025 13:29:24 +0100 Marc Zyngier <[email protected]> wrote:

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the TRBE driver over to this new method.

author maintainer
#17 lore raw

PATCH v4 8/26 perf: arm_pmu: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the OF side of the ARM PMU driver over to this new method.

---
 drivers/perf/arm_pmu_platform.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/perf/arm_pmu_platform.c +9 -7
index 118170a5cedef..9c0494d8a867a 100644
@@ -42,14 +42,13 @@ static int probe_current_pmu(struct arm_pmu *pmu,
 	return ret;
 }
 
-static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq)
+static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq,
+				const struct cpumask *affinity)
 {
-	int cpu, ret;
 	struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
+	int cpu;
 
-	ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus);
-	if (ret)
-		return ret;
+	cpumask_copy(&pmu->supported_cpus, affinity);
 
 	for_each_cpu(cpu, &pmu->supported_cpus)
 		per_cpu(hw_events->irq, cpu) = irq;
@@ -115,9 +114,12 @@ static int pmu_parse_irqs(struct arm_pmu *pmu)
 	}
 
 	if (num_irqs == 1) {
-		int irq = platform_get_irq(pdev, 0);
+		const struct cpumask *affinity;
+		int irq;
+
+		irq = platform_get_irq_affinity(pdev, 0, &affinity);
 		if ((irq > 0) && irq_is_percpu_devid(irq))
-			return pmu_parse_percpu_irq(pmu, irq);
+			return pmu_parse_percpu_irq(pmu, irq, affinity);
 	}
 
 	if (nr_cpu_ids != 1 && !pmu_has_irq_affinity(dev->of_node))
Signature · 1 line
2.47.3
merge bot Applied
#18 lore raw

[tip: irq/core] perf: arm_pmu: Convert to the new interrupt affinity retrieval API

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     663783e0013e97e18cc167139ab4319bbeaea399
Gitweb:        https://git.kernel.org/tip/663783e0013e97e18cc167139ab4319bbeaea399
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:25 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:33 +01:00

perf: arm_pmu: Convert to the new interrupt affinity retrieval API

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the OF side of the ARM PMU driver over to this new method.

---
 drivers/perf/arm_pmu_platform.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/perf/arm_pmu_platform.c +9 -7
index 118170a..9c0494d 100644
@@ -42,14 +42,13 @@ static int probe_current_pmu(struct arm_pmu *pmu,
 	return ret;
 }
 
-static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq)
+static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq,
+				const struct cpumask *affinity)
 {
-	int cpu, ret;
 	struct pmu_hw_events __percpu *hw_events = pmu->hw_events;
+	int cpu;
 
-	ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus);
-	if (ret)
-		return ret;
+	cpumask_copy(&pmu->supported_cpus, affinity);
 
 	for_each_cpu(cpu, &pmu->supported_cpus)
 		per_cpu(hw_events->irq, cpu) = irq;
@@ -115,9 +114,12 @@ static int pmu_parse_irqs(struct arm_pmu *pmu)
 	}
 
 	if (num_irqs == 1) {
-		int irq = platform_get_irq(pdev, 0);
+		const struct cpumask *affinity;
+		int irq;
+
+		irq = platform_get_irq_affinity(pdev, 0, &affinity);
 		if ((irq > 0) && irq_is_percpu_devid(irq))
-			return pmu_parse_percpu_irq(pmu, irq);
+			return pmu_parse_percpu_irq(pmu, irq, affinity);
 	}
 
 	if (nr_cpu_ids != 1 && !pmu_has_irq_affinity(dev->of_node))
Reviewed-by on v4 8/26
#19 lore raw

Re: [PATCH v4 08/26] perf: arm_pmu: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier
Quoted 7 lines · On Mon, 20 Oct 2025 13:29:25 +0100 Marc Zyngier <[email protected]> wrote:

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the OF side of the ARM PMU driver over to this new method.

author maintainer
#20 lore raw

PATCH v4 9/26 perf: arm_spe_pmu: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the ARM SPE driver over to this new method.

---
 drivers/perf/arm_spe_pmu.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/perf/arm_spe_pmu.c +4 -5
index fa50645feddad..1460b02d20e8b 100644
@@ -1287,8 +1287,10 @@ static void arm_spe_pmu_dev_teardown(struct arm_spe_pmu *spe_pmu)
 static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu)
 {
 	struct platform_device *pdev = spe_pmu->pdev;
-	int irq = platform_get_irq(pdev, 0);
+	const struct cpumask *affinity;
+	int irq;
 
+	irq = platform_get_irq_affinity(pdev, 0, &affinity);
 	if (irq < 0)
 		return -ENXIO;
 
@@ -1297,10 +1299,7 @@ static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu)
 		return -EINVAL;
 	}
 
-	if (irq_get_percpu_devid_partition(irq, &spe_pmu->supported_cpus)) {
-		dev_err(&pdev->dev, "failed to get PPI partition (%d)\n", irq);
-		return -EINVAL;
-	}
+	cpumask_copy(&spe_pmu->supported_cpus, affinity);
 
 	spe_pmu->irq = irq;
 	return 0;
Signature · 1 line
2.47.3
merge bot Applied
#21 lore raw

[tip: irq/core] perf: arm_spe_pmu: Convert to new interrupt affinity retrieval API

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     f6c8aced7c24e0c765d4283144d280c3f36e3906
Gitweb:        https://git.kernel.org/tip/f6c8aced7c24e0c765d4283144d280c3f36e3906
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:26 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:33 +01:00

perf: arm_spe_pmu: Convert to new interrupt affinity retrieval API

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the ARM SPE driver over to this new method.

---
 drivers/perf/arm_spe_pmu.c |  9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/perf/arm_spe_pmu.c +4 -5
index fa50645..1460b02 100644
@@ -1287,8 +1287,10 @@ static void arm_spe_pmu_dev_teardown(struct arm_spe_pmu *spe_pmu)
 static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu)
 {
 	struct platform_device *pdev = spe_pmu->pdev;
-	int irq = platform_get_irq(pdev, 0);
+	const struct cpumask *affinity;
+	int irq;
 
+	irq = platform_get_irq_affinity(pdev, 0, &affinity);
 	if (irq < 0)
 		return -ENXIO;
 
@@ -1297,10 +1299,7 @@ static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu)
 		return -EINVAL;
 	}
 
-	if (irq_get_percpu_devid_partition(irq, &spe_pmu->supported_cpus)) {
-		dev_err(&pdev->dev, "failed to get PPI partition (%d)\n", irq);
-		return -EINVAL;
-	}
+	cpumask_copy(&spe_pmu->supported_cpus, affinity);
 
 	spe_pmu->irq = irq;
 	return 0;
Reviewed-by on v4 9/26
#22 lore raw

Re: [PATCH v4 09/26] perf: arm_spe_pmu: Convert to new IRQ affinity retrieval API

In reply to Marc Zyngier
Quoted 7 lines · On Mon, 20 Oct 2025 13:29:26 +0100 Marc Zyngier <[email protected]> wrote:

Now that the relevant interrupt controllers are equipped with a callback returning the affinity of per-CPU interrupts, switch the ARM SPE driver over to this new method.

author maintainer
#23 lore raw

PATCH v4 10/26 irqchip/gic-v3: Switch high priority PPIs over to handle_percpu_devid_irq()

In reply to Marc Zyngier

It so appears that handle_percpu_devid_irq() is extremely similar to handle_percpu_devid_fasteoi_nmi(), and that the differences do no justify the horrid machinery we have in the GICv3 driver to handle the flow handler switch.

Let's stick with the standard flow handler, even for NMIs.

---
 drivers/irqchip/irq-gic-v3.c | 54 ++----------------------------------
 1 file changed, 2 insertions(+), 52 deletions(-)
drivers/irqchip/irq-gic-v3.c +2 -52
index cf0ba83c6eda6..dd2d6d722fc5e 100644
@@ -230,9 +230,6 @@ static void __init gic_prio_init(void)
 		!cpus_have_group0);
 }
 
-/* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */
-static refcount_t *rdist_nmi_refs;
-
 static struct gic_kvm_info gic_v3_kvm_info __initdata;
 static DEFINE_PER_CPU(bool, has_rss);
 
@@ -608,24 +605,6 @@ static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
 	}
 }
 
-static u32 __gic_get_rdist_index(irq_hw_number_t hwirq)
-{
-	switch (__get_intid_range(hwirq)) {
-	case SGI_RANGE:
-	case PPI_RANGE:
-		return hwirq;
-	case EPPI_RANGE:
-		return hwirq - EPPI_BASE_INTID + 32;
-	default:
-		unreachable();
-	}
-}
-
-static u32 gic_get_rdist_index(struct irq_data *d)
-{
-	return __gic_get_rdist_index(d->hwirq);
-}
-
 static int gic_irq_nmi_setup(struct irq_data *d)
 {
 	struct irq_desc *desc = irq_to_desc(d->irq);
@@ -646,20 +625,8 @@ static int gic_irq_nmi_setup(struct irq_data *d)
 		return -EINVAL;
 
 	/* desc lock should already be held */
-	if (gic_irq_in_rdist(d)) {
-		u32 idx = gic_get_rdist_index(d);
-
-		/*
-		 * Setting up a percpu interrupt as NMI, only switch handler
-		 * for first NMI
-		 */
-		if (!refcount_inc_not_zero(&rdist_nmi_refs[idx])) {
-			refcount_set(&rdist_nmi_refs[idx], 1);
-			desc->handle_irq = handle_percpu_devid_fasteoi_nmi;
-		}
-	} else {
+	if (!gic_irq_in_rdist(d))
 		desc->handle_irq = handle_fasteoi_nmi;
-	}
 
 	gic_irq_set_prio(d, dist_prio_nmi);
 
@@ -686,15 +653,8 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
 		return;
 
 	/* desc lock should already be held */
-	if (gic_irq_in_rdist(d)) {
-		u32 idx = gic_get_rdist_index(d);
-
-		/* Tearing down NMI, only switch handler for last NMI */
-		if (refcount_dec_and_test(&rdist_nmi_refs[idx]))
-			desc->handle_irq = handle_percpu_devid_irq;
-	} else {
+	if (!gic_irq_in_rdist(d))
 		desc->handle_irq = handle_fasteoi_irq;
-	}
 
 	gic_irq_set_prio(d, dist_prio_irq);
 }
@@ -2080,19 +2040,9 @@ static const struct gic_quirk gic_quirks[] = {
 
 static void gic_enable_nmi_support(void)
 {
-	int i;
-
 	if (!gic_prio_masking_enabled() || nmi_support_forbidden)
 		return;
 
-	rdist_nmi_refs = kcalloc(gic_data.ppi_nr + SGI_NR,
-				 sizeof(*rdist_nmi_refs), GFP_KERNEL);
-	if (!rdist_nmi_refs)
-		return;
-
-	for (i = 0; i < gic_data.ppi_nr + SGI_NR; i++)
-		refcount_set(&rdist_nmi_refs[i], 0);
-
 	pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n",
 		gic_has_relaxed_pmr_sync() ? "relaxed" : "forced");
 
Signature · 1 line
2.47.3
merge bot Applied
#24 lore raw

[tip: irq/core] irqchip/gic-v3: Switch high priority PPIs over to handle_percpu_devid_irq()

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     21bbbc50f398f5d58a14669ee18b10a2bd30e916
Gitweb:        https://git.kernel.org/tip/21bbbc50f398f5d58a14669ee18b10a2bd30e916
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:27 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:34 +01:00

irqchip/gic-v3: Switch high priority PPIs over to handle_percpu_devid_irq()

It so appears that handle_percpu_devid_irq() is extremely similar to handle_percpu_devid_fasteoi_nmi(), and that the differences do no justify the horrid machinery in the GICv3 driver to handle the flow handler switch.

Stick with the standard flow handler, even for NMIs.

---
 drivers/irqchip/irq-gic-v3.c | 54 +----------------------------------
 1 file changed, 2 insertions(+), 52 deletions(-)
drivers/irqchip/irq-gic-v3.c +2 -52
index cf0ba83..dd2d6d7 100644
@@ -230,9 +230,6 @@ static void __init gic_prio_init(void)
 		!cpus_have_group0);
 }
 
-/* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */
-static refcount_t *rdist_nmi_refs;
-
 static struct gic_kvm_info gic_v3_kvm_info __initdata;
 static DEFINE_PER_CPU(bool, has_rss);
 
@@ -608,24 +605,6 @@ static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
 	}
 }
 
-static u32 __gic_get_rdist_index(irq_hw_number_t hwirq)
-{
-	switch (__get_intid_range(hwirq)) {
-	case SGI_RANGE:
-	case PPI_RANGE:
-		return hwirq;
-	case EPPI_RANGE:
-		return hwirq - EPPI_BASE_INTID + 32;
-	default:
-		unreachable();
-	}
-}
-
-static u32 gic_get_rdist_index(struct irq_data *d)
-{
-	return __gic_get_rdist_index(d->hwirq);
-}
-
 static int gic_irq_nmi_setup(struct irq_data *d)
 {
 	struct irq_desc *desc = irq_to_desc(d->irq);
@@ -646,20 +625,8 @@ static int gic_irq_nmi_setup(struct irq_data *d)
 		return -EINVAL;
 
 	/* desc lock should already be held */
-	if (gic_irq_in_rdist(d)) {
-		u32 idx = gic_get_rdist_index(d);
-
-		/*
-		 * Setting up a percpu interrupt as NMI, only switch handler
-		 * for first NMI
-		 */
-		if (!refcount_inc_not_zero(&rdist_nmi_refs[idx])) {
-			refcount_set(&rdist_nmi_refs[idx], 1);
-			desc->handle_irq = handle_percpu_devid_fasteoi_nmi;
-		}
-	} else {
+	if (!gic_irq_in_rdist(d))
 		desc->handle_irq = handle_fasteoi_nmi;
-	}
 
 	gic_irq_set_prio(d, dist_prio_nmi);
 
@@ -686,15 +653,8 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
 		return;
 
 	/* desc lock should already be held */
-	if (gic_irq_in_rdist(d)) {
-		u32 idx = gic_get_rdist_index(d);
-
-		/* Tearing down NMI, only switch handler for last NMI */
-		if (refcount_dec_and_test(&rdist_nmi_refs[idx]))
-			desc->handle_irq = handle_percpu_devid_irq;
-	} else {
+	if (!gic_irq_in_rdist(d))
 		desc->handle_irq = handle_fasteoi_irq;
-	}
 
 	gic_irq_set_prio(d, dist_prio_irq);
 }
@@ -2080,19 +2040,9 @@ static const struct gic_quirk gic_quirks[] = {
 
 static void gic_enable_nmi_support(void)
 {
-	int i;
-
 	if (!gic_prio_masking_enabled() || nmi_support_forbidden)
 		return;
 
-	rdist_nmi_refs = kcalloc(gic_data.ppi_nr + SGI_NR,
-				 sizeof(*rdist_nmi_refs), GFP_KERNEL);
-	if (!rdist_nmi_refs)
-		return;
-
-	for (i = 0; i < gic_data.ppi_nr + SGI_NR; i++)
-		refcount_set(&rdist_nmi_refs[i], 0);
-
 	pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n",
 		gic_has_relaxed_pmr_sync() ? "relaxed" : "forced");
 
Reviewed-by on v4 10/26
#25 lore raw

Re: [PATCH v4 10/26] irqchip/gic-v3: Switch high priority PPIs over to handle_percpu_devid_irq()

In reply to Marc Zyngier
Quoted 10 lines · On Mon, 20 Oct 2025 13:29:27 +0100 Marc Zyngier <[email protected]> wrote:

It so appears that handle_percpu_devid_irq() is extremely similar to handle_percpu_devid_fasteoi_nmi(), and that the differences do no justify the horrid machinery we have in the GICv3 driver to handle the flow handler switch.

Let's stick with the standard flow handler, even for NMIs.

LGTM and who doesn't like those diff stats ;)

Quoted 3 lines
---
 drivers/irqchip/irq-gic-v3.c | 54 ++----------------------------------
 1 file changed, 2 insertions(+), 52 deletions(-)
author maintainer
#26 lore raw

PATCH v4 11/26 genirq: Kill handle_percpu_devid_fasteoi_nmi()

In reply to Marc Zyngier

There is no in-tree user of this flow handler anymore, so simply remove it.

---
 include/linux/irq.h |  1 -
 kernel/irq/chip.c   | 25 -------------------------
 2 files changed, 26 deletions(-)
include/linux/irq.h +0 -1
index c67e76fbcc077..b728c18f6ded7 100644
@@ -655,7 +655,6 @@ extern void handle_bad_irq(struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
 extern void handle_fasteoi_nmi(struct irq_desc *desc);
-extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc);
 
 extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
 extern int irq_chip_pm_get(struct irq_data *data);
kernel/irq/chip.c +0 -25
index 3ffa0d80ddd19..633e1f67bb6f4 100644
@@ -929,31 +929,6 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 		chip->irq_eoi(&desc->irq_data);
 }
 
-/**
- * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu
- *				     dev ids
- * @desc:	the interrupt description structure for this irq
- *
- * Similar to handle_fasteoi_nmi, but handling the dev_id cookie
- * as a percpu pointer.
- */
-void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct irqaction *action = desc->action;
-	unsigned int irq = irq_desc_get_irq(desc);
-	irqreturn_t res;
-
-	__kstat_incr_irqs_this_cpu(desc);
-
-	trace_irq_handler_entry(irq, action);
-	res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
-	trace_irq_handler_exit(irq, action, res);
-
-	if (chip->irq_eoi)
-		chip->irq_eoi(&desc->irq_data);
-}
-
 static void
 __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
 		     int is_chained, const char *name)
Signature · 1 line
2.47.3
merge bot Applied
#27 lore raw

[tip: irq/core] genirq: Kill handle_percpu_devid_fasteoi_nmi()

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     5ff78c8de9d83ad6fc0553bf8f2edc816385837d
Gitweb:        https://git.kernel.org/tip/5ff78c8de9d83ad6fc0553bf8f2edc816385837d
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:28 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:34 +01:00

genirq: Kill handle_percpu_devid_fasteoi_nmi()

There is no in-tree user of this flow handler anymore, so simply remove it.

---
 include/linux/irq.h |  1 -
 kernel/irq/chip.c   | 25 -------------------------
 2 files changed, 26 deletions(-)
include/linux/irq.h +0 -1
index c67e76f..b728c18 100644
@@ -655,7 +655,6 @@ extern void handle_bad_irq(struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
 extern void handle_fasteoi_nmi(struct irq_desc *desc);
-extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc);
 
 extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
 extern int irq_chip_pm_get(struct irq_data *data);
kernel/irq/chip.c +0 -25
index 3ffa0d8..633e1f6 100644
@@ -929,31 +929,6 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 		chip->irq_eoi(&desc->irq_data);
 }
 
-/**
- * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu
- *				     dev ids
- * @desc:	the interrupt description structure for this irq
- *
- * Similar to handle_fasteoi_nmi, but handling the dev_id cookie
- * as a percpu pointer.
- */
-void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct irqaction *action = desc->action;
-	unsigned int irq = irq_desc_get_irq(desc);
-	irqreturn_t res;
-
-	__kstat_incr_irqs_this_cpu(desc);
-
-	trace_irq_handler_entry(irq, action);
-	res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
-	trace_irq_handler_exit(irq, action, res);
-
-	if (chip->irq_eoi)
-		chip->irq_eoi(&desc->irq_data);
-}
-
 static void
 __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
 		     int is_chained, const char *name)
Reviewed-by on v4 11/26
#28 lore raw

Re: [PATCH v4 11/26] genirq: Kill handle_percpu_devid_fasteoi_nmi()

In reply to Marc Zyngier
Quoted 6 lines · On Mon, 20 Oct 2025 13:29:28 +0100 Marc Zyngier <[email protected]> wrote:

There is no in-tree user of this flow handler anymore, so simply remove it.

author maintainer
#29 lore raw

PATCH v4 12/26 genirq: Merge irqaction::{dev_id,percpu_dev_id}

In reply to Marc Zyngier

When irqaction::percpu_dev_id was introduced, it was hoped that it could be part of an anonymous union with dev_id, as the two fields are mutually exclusive.

However, toolchains used at the time were often showing terrible support for anonymous unions, breaking the build on a number of architectures. It was therefore decided to keep the two fields separate and address this down the line.

14 years later, the compiler dark age is over, and there is universal support for anonymous unions. Let's get a whole pointer back that can immediately be spent on something else.

---
 include/linux/interrupt.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
include/linux/interrupt.h +4 -2
index 51b6484c04934..0ec1a71ab4e84 100644
@@ -121,8 +121,10 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
  */
 struct irqaction {
 	irq_handler_t		handler;
-	void			*dev_id;
-	void __percpu		*percpu_dev_id;
+	union {
+		void		*dev_id;
+		void __percpu	*percpu_dev_id;
+	};
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;
Signature · 1 line
2.47.3
merge bot Applied
#30 lore raw

[tip: irq/core] genirq: Merge irqaction::{dev_id,percpu_dev_id}

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     5c2b2cc472e015e79c4f0170893a1e0883bd3bb4
Gitweb:        https://git.kernel.org/tip/5c2b2cc472e015e79c4f0170893a1e0883bd3bb4
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:29 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:34 +01:00

genirq: Merge irqaction::{dev_id,percpu_dev_id}

When irqaction::percpu_dev_id was introduced, it was hoped that it could be part of an anonymous union with dev_id, as the two fields are mutually exclusive.

However, toolchains used at the time were often showing terrible support for anonymous unions, breaking the build on a number of architectures. It was therefore decided to keep the two fields separate and address this down the line.

14 years later, the compiler dark age is over, and there is universal support for anonymous unions. Get a whole pointer back that can immediately be spent on something else.

---
 include/linux/interrupt.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
include/linux/interrupt.h +4 -2
index 51b6484..0ec1a71 100644
@@ -121,8 +121,10 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
  */
 struct irqaction {
 	irq_handler_t		handler;
-	void			*dev_id;
-	void __percpu		*percpu_dev_id;
+	union {
+		void		*dev_id;
+		void __percpu	*percpu_dev_id;
+	};
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;
Reviewed-by on v4 12/26
#31 lore raw

Re: [PATCH v4 12/26] genirq: Merge irqaction::{dev_id,percpu_dev_id}

In reply to Marc Zyngier
Quoted 9 lines · On Mon, 20 Oct 2025 13:29:29 +0100 Marc Zyngier <[email protected]> wrote:

When irqaction::percpu_dev_id was introduced, it was hoped that it could be part of an anonymous union with dev_id, as the two fields are mutually exclusive.

However, toolchains used at the time were often showing terrible support for anonymous unions, breaking the build on a number of architectures. It was therefore decided to keep the two fields separate and address this down the line.

Quoted 6 lines

14 years later, the compiler dark age is over, and there is universal support for anonymous unions. Let's get a whole pointer back that can immediately be spent on something else.

I'm glad I either never saw that anon union problem or have blanked it from my mind.

author maintainer
#32 lore raw

PATCH v4 13/26 genirq: Factor-in percpu irqaction creation

In reply to Marc Zyngier

Move the code creating a per-cpu irqaction into its own helper, so that future changes to this code can be kept localised.

At the same time, fix the documentation which appears to say the wrong thing when it comes to interrupts being automatically enabled (percpu_devid interrupts never are).

---
 kernel/irq/manage.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)
kernel/irq/manage.c +24 -16
index c94837382037e..d9ddc30678b5d 100644
@@ -2442,6 +2442,24 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 	return retval;
 }
 
+static
+struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags,
+					  const char *devname, void __percpu *dev_id)
+{
+	struct irqaction *action;
+
+	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return NULL;
+
+	action->handler = handler;
+	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
+	action->name = devname;
+	action->percpu_dev_id = dev_id;
+
+	return action;
+}
+
 /**
  * __request_percpu_irq - allocate a percpu interrupt line
  * @irq:	Interrupt line to allocate
@@ -2450,9 +2468,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
  * @devname:	An ascii name for the claiming device
  * @dev_id:	A percpu cookie passed back to the handler function
  *
- * This call allocates interrupt resources and enables the interrupt on the
- * local CPU. If the interrupt is supposed to be enabled on other CPUs, it
- * has to be done on each CPU using enable_percpu_irq().
+ * This call allocates interrupt resources, but doesn't enable the interrupt
+ * on any CPU, as all percpu-devid interrupts are flagged with IRQ_NOAUTOEN.
+ * It has to be done on each CPU using enable_percpu_irq().
  *
  * @dev_id must be globally unique. It is a per-cpu variable, and
  * the handler gets called with the interrupted CPU's instance of
@@ -2477,15 +2495,10 @@ int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 	if (flags && flags != IRQF_TIMER)
 		return -EINVAL;
 
-	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = create_percpu_irqaction(handler, flags, devname, dev_id);
 	if (!action)
 		return -ENOMEM;
 
-	action->handler = handler;
-	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
-	action->name = devname;
-	action->percpu_dev_id = dev_id;
-
 	retval = irq_chip_pm_get(&desc->irq_data);
 	if (retval < 0) {
 		kfree(action);
@@ -2546,16 +2559,11 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 	if (irq_is_nmi(desc))
 		return -EINVAL;
 
-	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
+					 name, dev_id);
 	if (!action)
 		return -ENOMEM;
 
-	action->handler = handler;
-	action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND | IRQF_NO_THREAD
-		| IRQF_NOBALANCING;
-	action->name = name;
-	action->percpu_dev_id = dev_id;
-
 	retval = irq_chip_pm_get(&desc->irq_data);
 	if (retval < 0)
 		goto err_out;
Signature · 1 line
2.47.3
merge bot Applied
#33 lore raw

[tip: irq/core] genirq: Factor-in percpu irqaction creation

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     9047a39daa7832e40a9ae2d190ae5e7b351a9121
Gitweb:        https://git.kernel.org/tip/9047a39daa7832e40a9ae2d190ae5e7b351a9121
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:30 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:34 +01:00

genirq: Factor-in percpu irqaction creation

Move the code creating a per-cpu irqaction into its own helper, so that future changes to this code can be kept localised.

At the same time, fix the documentation which appears to say the wrong thing when it comes to interrupts being automatically enabled (percpu_devid interrupts never are).

---
 kernel/irq/manage.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)
kernel/irq/manage.c +24 -16
index c948373..d9ddc30 100644
@@ -2442,6 +2442,24 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 	return retval;
 }
 
+static
+struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags,
+					  const char *devname, void __percpu *dev_id)
+{
+	struct irqaction *action;
+
+	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return NULL;
+
+	action->handler = handler;
+	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
+	action->name = devname;
+	action->percpu_dev_id = dev_id;
+
+	return action;
+}
+
 /**
  * __request_percpu_irq - allocate a percpu interrupt line
  * @irq:	Interrupt line to allocate
@@ -2450,9 +2468,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
  * @devname:	An ascii name for the claiming device
  * @dev_id:	A percpu cookie passed back to the handler function
  *
- * This call allocates interrupt resources and enables the interrupt on the
- * local CPU. If the interrupt is supposed to be enabled on other CPUs, it
- * has to be done on each CPU using enable_percpu_irq().
+ * This call allocates interrupt resources, but doesn't enable the interrupt
+ * on any CPU, as all percpu-devid interrupts are flagged with IRQ_NOAUTOEN.
+ * It has to be done on each CPU using enable_percpu_irq().
  *
  * @dev_id must be globally unique. It is a per-cpu variable, and
  * the handler gets called with the interrupted CPU's instance of
@@ -2477,15 +2495,10 @@ int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 	if (flags && flags != IRQF_TIMER)
 		return -EINVAL;
 
-	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = create_percpu_irqaction(handler, flags, devname, dev_id);
 	if (!action)
 		return -ENOMEM;
 
-	action->handler = handler;
-	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
-	action->name = devname;
-	action->percpu_dev_id = dev_id;
-
 	retval = irq_chip_pm_get(&desc->irq_data);
 	if (retval < 0) {
 		kfree(action);
@@ -2546,16 +2559,11 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 	if (irq_is_nmi(desc))
 		return -EINVAL;
 
-	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
+					 name, dev_id);
 	if (!action)
 		return -ENOMEM;
 
-	action->handler = handler;
-	action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND | IRQF_NO_THREAD
-		| IRQF_NOBALANCING;
-	action->name = name;
-	action->percpu_dev_id = dev_id;
-
 	retval = irq_chip_pm_get(&desc->irq_data);
 	if (retval < 0)
 		goto err_out;
author maintainer
#34 lore raw

PATCH v4 14/26 genirq: Add affinity to percpu_devid interrupt requests

In reply to Marc Zyngier

Add an affinity field to both the irqaction structure and the interrupt request primitives. Nothing is making use of it yet, and the only value used it NULL, which is used as a shorthand for cpu_possible_mask.

This will shortly get used with actual affinities.

---
 include/linux/interrupt.h |  5 +++--
 kernel/irq/manage.c       | 14 ++++++++++----
 2 files changed, 13 insertions(+), 6 deletions(-)
include/linux/interrupt.h +3 -2
index 0ec1a71ab4e84..52147d5f432b3 100644
@@ -125,6 +125,7 @@ struct irqaction {
 		void		*dev_id;
 		void __percpu	*percpu_dev_id;
 	};
+	const struct cpumask	*affinity;
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;
@@ -181,7 +182,7 @@ request_any_context_irq(unsigned int irq, irq_handler_t handler,
 extern int __must_check
 __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 		     unsigned long flags, const char *devname,
-		     void __percpu *percpu_dev_id);
+		     const cpumask_t *affinity, void __percpu *percpu_dev_id);
 
 extern int __must_check
 request_nmi(unsigned int irq, irq_handler_t handler, unsigned long flags,
@@ -192,7 +193,7 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 		   const char *devname, void __percpu *percpu_dev_id)
 {
 	return __request_percpu_irq(irq, handler, 0,
-				    devname, percpu_dev_id);
+				    devname, NULL, percpu_dev_id);
 }
 
 extern int __must_check
kernel/irq/manage.c +10 -4
index d9ddc30678b5d..5f4c651677436 100644
@@ -2444,10 +2444,14 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 
 static
 struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags,
-					  const char *devname, void __percpu *dev_id)
+					  const char *devname, const cpumask_t *affinity,
+					  void __percpu *dev_id)
 {
 	struct irqaction *action;
 
+	if (!affinity)
+		affinity = cpu_possible_mask;
+
 	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return NULL;
@@ -2456,6 +2460,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
 	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
 	action->name = devname;
 	action->percpu_dev_id = dev_id;
+	action->affinity = affinity;
 
 	return action;
 }
@@ -2466,6 +2471,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
  * @handler:	Function to be called when the IRQ occurs.
  * @flags:	Interrupt type flags (IRQF_TIMER only)
  * @devname:	An ascii name for the claiming device
+ * @affinity:	A cpumask describing the target CPUs for this interrupt
  * @dev_id:	A percpu cookie passed back to the handler function
  *
  * This call allocates interrupt resources, but doesn't enable the interrupt
@@ -2478,7 +2484,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
  */
 int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 			 unsigned long flags, const char *devname,
-			 void __percpu *dev_id)
+			 const cpumask_t *affinity, void __percpu *dev_id)
 {
 	struct irqaction *action;
 	struct irq_desc *desc;
@@ -2495,7 +2501,7 @@ int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 	if (flags && flags != IRQF_TIMER)
 		return -EINVAL;
 
-	action = create_percpu_irqaction(handler, flags, devname, dev_id);
+	action = create_percpu_irqaction(handler, flags, devname, affinity, dev_id);
 	if (!action)
 		return -ENOMEM;
 
@@ -2560,7 +2566,7 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 		return -EINVAL;
 
 	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
-					 name, dev_id);
+					 name, NULL, dev_id);
 	if (!action)
 		return -ENOMEM;
 
Signature · 1 line
2.47.3
merge bot Applied
#35 lore raw

[tip: irq/core] genirq: Add affinity to percpu_devid interrupt requests

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     258e7d28a3dcd389239f9688058140c1a418b549
Gitweb:        https://git.kernel.org/tip/258e7d28a3dcd389239f9688058140c1a418b549
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:31 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:34 +01:00

genirq: Add affinity to percpu_devid interrupt requests

Add an affinity field to both the irqaction structure and the interrupt request primitives. Nothing is making use of it yet, and the only value used it NULL, which is used as a shorthand for cpu_possible_mask.

This will shortly get used with actual affinities.

---
 include/linux/interrupt.h |  5 +++--
 kernel/irq/manage.c       | 14 ++++++++++----
 2 files changed, 13 insertions(+), 6 deletions(-)
include/linux/interrupt.h +3 -2
index 0ec1a71..52147d5 100644
@@ -125,6 +125,7 @@ struct irqaction {
 		void		*dev_id;
 		void __percpu	*percpu_dev_id;
 	};
+	const struct cpumask	*affinity;
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;
@@ -181,7 +182,7 @@ request_any_context_irq(unsigned int irq, irq_handler_t handler,
 extern int __must_check
 __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 		     unsigned long flags, const char *devname,
-		     void __percpu *percpu_dev_id);
+		     const cpumask_t *affinity, void __percpu *percpu_dev_id);
 
 extern int __must_check
 request_nmi(unsigned int irq, irq_handler_t handler, unsigned long flags,
@@ -192,7 +193,7 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 		   const char *devname, void __percpu *percpu_dev_id)
 {
 	return __request_percpu_irq(irq, handler, 0,
-				    devname, percpu_dev_id);
+				    devname, NULL, percpu_dev_id);
 }
 
 extern int __must_check
kernel/irq/manage.c +10 -4
index d9ddc30..5f4c651 100644
@@ -2444,10 +2444,14 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 
 static
 struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags,
-					  const char *devname, void __percpu *dev_id)
+					  const char *devname, const cpumask_t *affinity,
+					  void __percpu *dev_id)
 {
 	struct irqaction *action;
 
+	if (!affinity)
+		affinity = cpu_possible_mask;
+
 	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return NULL;
@@ -2456,6 +2460,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
 	action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
 	action->name = devname;
 	action->percpu_dev_id = dev_id;
+	action->affinity = affinity;
 
 	return action;
 }
@@ -2466,6 +2471,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
  * @handler:	Function to be called when the IRQ occurs.
  * @flags:	Interrupt type flags (IRQF_TIMER only)
  * @devname:	An ascii name for the claiming device
+ * @affinity:	A cpumask describing the target CPUs for this interrupt
  * @dev_id:	A percpu cookie passed back to the handler function
  *
  * This call allocates interrupt resources, but doesn't enable the interrupt
@@ -2478,7 +2484,7 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
  */
 int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 			 unsigned long flags, const char *devname,
-			 void __percpu *dev_id)
+			 const cpumask_t *affinity, void __percpu *dev_id)
 {
 	struct irqaction *action;
 	struct irq_desc *desc;
@@ -2495,7 +2501,7 @@ int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
 	if (flags && flags != IRQF_TIMER)
 		return -EINVAL;
 
-	action = create_percpu_irqaction(handler, flags, devname, dev_id);
+	action = create_percpu_irqaction(handler, flags, devname, affinity, dev_id);
 	if (!action)
 		return -ENOMEM;
 
@@ -2560,7 +2566,7 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 		return -EINVAL;
 
 	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
-					 name, dev_id);
+					 name, NULL, dev_id);
 	if (!action)
 		return -ENOMEM;
 
Reviewed-by on v4 14/26
#36 lore raw

Re: [PATCH v4 14/26] genirq: Add affinity to percpu_devid interrupt requests

In reply to Marc Zyngier
Quoted 3 lines · On Mon, 20 Oct 2025 13:29:31 +0100 Marc Zyngier <[email protected]> wrote:

Add an affinity field to both the irqaction structure and the interrupt request primitives. Nothing is making use of it yet, and the only value used it NULL, which is used as a shorthand for cpu_possible_mask.

used is NULL

Quoted 5 lines

This will shortly get used with actual affinities.

With trivial bit of documentation added

Quoted 10 lines
---
 include/linux/interrupt.h |  5 +++--
 kernel/irq/manage.c       | 14 ++++++++++----
 2 files changed, 13 insertions(+), 6 deletions(-)
include/linux/interrupt.h +0 -0
index 0ec1a71ab4e84..52147d5f432b3 100644

include/linux/interrupt.h struct irqaction { · line 128

Quoted 4 lines
include/linux/interrupt.h +1 -0
@@ -125,6 +125,7 @@ struct irqaction {
 		void		*dev_id;
 		void __percpu	*percpu_dev_id;
 	};
+	const struct cpumask	*affinity;

This structure has kernel-doc that needs an update.

Quoted 3 lines
include/linux/interrupt.h +0 -0
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;
author maintainer
#37 lore raw

Re: [PATCH v4 14/26] genirq: Add affinity to percpu_devid interrupt requests

Quoted 24 lines · Jonathan Cameron
Quoted 3 lines · On Mon, 20 Oct 2025 13:29:31 +0100 Marc Zyngier <[email protected]> wrote:

Add an affinity field to both the irqaction structure and the interrupt request primitives. Nothing is making use of it yet, and the only value used it NULL, which is used as a shorthand for cpu_possible_mask.

used is NULL

Quoted 5 lines

This will shortly get used with actual affinities.

With trivial bit of documentation added

Quoted 5 lines
---
 include/linux/interrupt.h |  5 +++--
 kernel/irq/manage.c       | 14 ++++++++++----
 2 files changed, 13 insertions(+), 6 deletions(-)
Quoted 15 lines

include/linux/interrupt.h struct irqaction { · line 128

Quoted 9 lines
include/linux/interrupt.h +1 -0
index 0ec1a71ab4e84..52147d5f432b3 100644
@@ -125,6 +125,7 @@ struct irqaction {
 		void		*dev_id;
 		void __percpu	*percpu_dev_id;
 	};
+	const struct cpumask	*affinity;

This structure has kernel-doc that needs an update.

Quoted 3 lines
include/linux/interrupt.h +0 -0
 	struct irqaction	*next;
 	irq_handler_t		thread_fn;
 	struct task_struct	*thread;

See 68c4c159a0db4 ("genirq: Fix percpu_devid irq affinity documentation") in -next for the merged fix.

Thanks,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
author maintainer
#38 lore raw

PATCH v4 15/26 genirq: Update request_percpu_nmi() to take an affinity

In reply to Marc Zyngier

Continue spreading the notion of affinity to the percpu interrupt request code by updating the call sites that use request_percpu_nmi() (all two of them) to take an affinity pointer. This pointer is firmly NULL for now.

---
 arch/arm64/kernel/smp.c   |  2 +-
 drivers/perf/arm_pmu.c    |  2 +-
 include/linux/interrupt.h |  4 ++--
 kernel/irq/manage.c       | 12 +++++++-----
 4 files changed, 11 insertions(+), 9 deletions(-)
arch/arm64/kernel/smp.c +1 -1
index 68cea3a4a35ca..6fb838eee2e7d 100644
@@ -1094,7 +1094,7 @@ static void ipi_setup_sgi(int ipi)
 	irq = ipi_irq_base + ipi;
 
 	if (ipi_should_be_nmi(ipi)) {
-		err = request_percpu_nmi(irq, ipi_handler, "IPI", &irq_stat);
+		err = request_percpu_nmi(irq, ipi_handler, "IPI", NULL, &irq_stat);
 		WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err);
 	} else {
 		err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);
drivers/perf/arm_pmu.c +1 -1
index 5c310e803dd78..22c601b46c858 100644
@@ -659,7 +659,7 @@ int armpmu_request_irq(int irq, int cpu)
 			irq_ops = &pmunmi_ops;
 		}
 	} else if (armpmu_count_irq_users(irq) == 0) {
-		err = request_percpu_nmi(irq, handler, "arm-pmu", &cpu_armpmu);
+		err = request_percpu_nmi(irq, handler, "arm-pmu", NULL, &cpu_armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
include/linux/interrupt.h +2 -2
index 52147d5f432b3..81506ab759b81 100644
@@ -197,8 +197,8 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 }
 
 extern int __must_check
-request_percpu_nmi(unsigned int irq, irq_handler_t handler,
-		   const char *devname, void __percpu *dev);
+request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
+		   const struct cpumask *affinity, void __percpu *dev_id);
 
 extern const void *free_irq(unsigned int, void *);
 extern void free_percpu_irq(unsigned int, void __percpu *);
kernel/irq/manage.c +7 -5
index 5f4c651677436..b1a3140e5f3c9 100644
@@ -2527,6 +2527,7 @@ EXPORT_SYMBOL_GPL(__request_percpu_irq);
  * @irq:	Interrupt line to allocate
  * @handler:	Function to be called when the IRQ occurs.
  * @name:	An ascii name for the claiming device
+ * @affinity:	A cpumask describing the target CPUs for this interrupt
  * @dev_id:	A percpu cookie passed back to the handler function
  *
  * This call allocates interrupt resources for a per CPU NMI. Per CPU NMIs
@@ -2543,8 +2544,8 @@ EXPORT_SYMBOL_GPL(__request_percpu_irq);
  * If the interrupt line cannot be used to deliver NMIs, function
  * will fail returning a negative value.
  */
-int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
-		       const char *name, void __percpu *dev_id)
+int request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
+		       const struct cpumask *affinity, void __percpu *dev_id)
 {
 	struct irqaction *action;
 	struct irq_desc *desc;
@@ -2561,12 +2562,13 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 	    !irq_supports_nmi(desc))
 		return -EINVAL;
 
-	/* The line cannot already be NMI */
-	if (irq_is_nmi(desc))
+	/* The line cannot be NMI already if the new request covers all CPUs */
+	if (irq_is_nmi(desc) &&
+	    (!affinity || cpumask_equal(affinity, cpu_possible_mask)))
 		return -EINVAL;
 
 	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
-					 name, NULL, dev_id);
+					 name, affinity, dev_id);
 	if (!action)
 		return -ENOMEM;
 
Signature · 1 line
2.47.3
merge bot Applied
#39 lore raw

[tip: irq/core] genirq: Update request_percpu_nmi() to take an affinity

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     b9c6aa9efc71dae656f9f913d1250ea08cd6e10f
Gitweb:        https://git.kernel.org/tip/b9c6aa9efc71dae656f9f913d1250ea08cd6e10f
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:32 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:35 +01:00

genirq: Update request_percpu_nmi() to take an affinity

Continue spreading the notion of affinity to the per CPU interrupt request code by updating the call sites that use request_percpu_nmi() (all two of them) to take an affinity pointer. This pointer is firmly NULL for now.

---
 arch/arm64/kernel/smp.c   |  2 +-
 drivers/perf/arm_pmu.c    |  2 +-
 include/linux/interrupt.h |  4 ++--
 kernel/irq/manage.c       | 12 +++++++-----
 4 files changed, 11 insertions(+), 9 deletions(-)
arch/arm64/kernel/smp.c +1 -1
index 68cea3a..6fb838e 100644
@@ -1094,7 +1094,7 @@ static void ipi_setup_sgi(int ipi)
 	irq = ipi_irq_base + ipi;
 
 	if (ipi_should_be_nmi(ipi)) {
-		err = request_percpu_nmi(irq, ipi_handler, "IPI", &irq_stat);
+		err = request_percpu_nmi(irq, ipi_handler, "IPI", NULL, &irq_stat);
 		WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err);
 	} else {
 		err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);
drivers/perf/arm_pmu.c +1 -1
index 5c310e8..22c601b 100644
@@ -659,7 +659,7 @@ int armpmu_request_irq(int irq, int cpu)
 			irq_ops = &pmunmi_ops;
 		}
 	} else if (armpmu_count_irq_users(irq) == 0) {
-		err = request_percpu_nmi(irq, handler, "arm-pmu", &cpu_armpmu);
+		err = request_percpu_nmi(irq, handler, "arm-pmu", NULL, &cpu_armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
include/linux/interrupt.h +2 -2
index 52147d5..81506ab 100644
@@ -197,8 +197,8 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 }
 
 extern int __must_check
-request_percpu_nmi(unsigned int irq, irq_handler_t handler,
-		   const char *devname, void __percpu *dev);
+request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
+		   const struct cpumask *affinity, void __percpu *dev_id);
 
 extern const void *free_irq(unsigned int, void *);
 extern void free_percpu_irq(unsigned int, void __percpu *);
kernel/irq/manage.c +7 -5
index 5f4c651..b1a3140 100644
@@ -2527,6 +2527,7 @@ EXPORT_SYMBOL_GPL(__request_percpu_irq);
  * @irq:	Interrupt line to allocate
  * @handler:	Function to be called when the IRQ occurs.
  * @name:	An ascii name for the claiming device
+ * @affinity:	A cpumask describing the target CPUs for this interrupt
  * @dev_id:	A percpu cookie passed back to the handler function
  *
  * This call allocates interrupt resources for a per CPU NMI. Per CPU NMIs
@@ -2543,8 +2544,8 @@ EXPORT_SYMBOL_GPL(__request_percpu_irq);
  * If the interrupt line cannot be used to deliver NMIs, function
  * will fail returning a negative value.
  */
-int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
-		       const char *name, void __percpu *dev_id)
+int request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
+		       const struct cpumask *affinity, void __percpu *dev_id)
 {
 	struct irqaction *action;
 	struct irq_desc *desc;
@@ -2561,12 +2562,13 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
 	    !irq_supports_nmi(desc))
 		return -EINVAL;
 
-	/* The line cannot already be NMI */
-	if (irq_is_nmi(desc))
+	/* The line cannot be NMI already if the new request covers all CPUs */
+	if (irq_is_nmi(desc) &&
+	    (!affinity || cpumask_equal(affinity, cpu_possible_mask)))
 		return -EINVAL;
 
 	action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
-					 name, NULL, dev_id);
+					 name, affinity, dev_id);
 	if (!action)
 		return -ENOMEM;
 
Reviewed-by on v4 15/26
#40 lore raw

Re: [PATCH v4 15/26] genirq: Update request_percpu_nmi() to take an affinity

In reply to Marc Zyngier
Quoted 7 lines · On Mon, 20 Oct 2025 13:29:32 +0100 Marc Zyngier <[email protected]> wrote:

Continue spreading the notion of affinity to the percpu interrupt request code by updating the call sites that use request_percpu_nmi() (all two of them) to take an affinity pointer. This pointer is firmly NULL for now.

author maintainer
#41 lore raw

PATCH v4 16/26 genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

In reply to Marc Zyngier

Interrupt sharing for percpu-devid interrupts is forbidden, and for good reasons. These are interrupts generated *from* a CPU and handled by itself (timer, for example). Nobody in their right mind would put two devices on the same pin (and if they have, they get to keep the pieces...).

But this also prevents more benign cases, where devices are connected to groups of CPUs, and for which the affinities are not overlapping. Effectively, the only thing they share is the interrupt number, and nothing else.

Let's tweak the definition of IRQF_SHARED applied to percpu_devid interrupts to allow this particular case. This results in extra validation at the point of the interrupt being setup and freed, as well as a tiny bit of extra complexity for interrupts at handling time (to pick the correct irqaction).

---
 kernel/irq/chip.c   |  8 ++++--
 kernel/irq/manage.c | 67 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 61 insertions(+), 14 deletions(-)
kernel/irq/chip.c +6 -2
index 633e1f67bb6f4..19e0a87a2663e 100644
@@ -897,8 +897,9 @@ void handle_percpu_irq(struct irq_desc *desc)
 void handle_percpu_devid_irq(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct irqaction *action = desc->action;
 	unsigned int irq = irq_desc_get_irq(desc);
+	unsigned int cpu = smp_processor_id();
+	struct irqaction *action;
 	irqreturn_t res;
 
 	/*
@@ -910,12 +911,15 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 	if (chip->irq_ack)
 		chip->irq_ack(&desc->irq_data);
 
+	for (action = desc->action; action; action = action->next)
+		if (cpumask_test_cpu(cpu, action->affinity))
+			break;
+
 	if (likely(action)) {
 		trace_irq_handler_entry(irq, action);
 		res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
 		trace_irq_handler_exit(irq, action, res);
 	} else {
-		unsigned int cpu = smp_processor_id();
 		bool enabled = cpumask_test_cpu(cpu, desc->percpu_enabled);
 
 		if (enabled)
kernel/irq/manage.c +55 -12

127 lines not on this page · raw message

Signature · 1 line
2.47.3
merge bot Applied
#42 lore raw

[tip: irq/core] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     bdf4e2ac295fe77c94b570a1ad12c0882bc89b53
Gitweb:        https://git.kernel.org/tip/bdf4e2ac295fe77c94b570a1ad12c0882bc89b53
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:33 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:35 +01:00

genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

Interrupt sharing for percpu-devid interrupts is forbidden, and for good reasons. These are interrupts generated *from* a CPU and handled by itself (timer, for example). Nobody in their right mind would put two devices on the same pin (and if they have, they get to keep the pieces...).

But this also prevents more benign cases, where devices are connected to groups of CPUs, and for which the affinities are not overlapping. Effectively, the only thing they share is the interrupt number, and nothing else.

Tweak the definition of IRQF_SHARED applied to percpu_devid interrupts to allow this particular use case. This results in extra validation at the point of the interrupt being setup and freed, as well as a tiny bit of extra complexity for interrupts at handling time (to pick the correct irqaction).

---
 kernel/irq/chip.c   |  8 +++--
 kernel/irq/manage.c | 67 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 61 insertions(+), 14 deletions(-)
kernel/irq/chip.c +6 -2
index 633e1f6..19e0a87 100644
@@ -897,8 +897,9 @@ void handle_percpu_irq(struct irq_desc *desc)
 void handle_percpu_devid_irq(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct irqaction *action = desc->action;
 	unsigned int irq = irq_desc_get_irq(desc);
+	unsigned int cpu = smp_processor_id();
+	struct irqaction *action;
 	irqreturn_t res;
 
 	/*
@@ -910,12 +911,15 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 	if (chip->irq_ack)
 		chip->irq_ack(&desc->irq_data);
 
+	for (action = desc->action; action; action = action->next)
+		if (cpumask_test_cpu(cpu, action->affinity))
+			break;
+
 	if (likely(action)) {
 		trace_irq_handler_entry(irq, action);
 		res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
 		trace_irq_handler_exit(irq, action, res);
 	} else {
-		unsigned int cpu = smp_processor_id();
 		bool enabled = cpumask_test_cpu(cpu, desc->percpu_enabled);
 
 		if (enabled)
kernel/irq/manage.c +55 -12

127 lines not on this page · raw message

Reviewed-by on v4 16/26
#43 lore raw

Re: [PATCH v4 16/26] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

In reply to Marc Zyngier
Quoted 11 lines · On Mon, 20 Oct 2025 13:29:33 +0100 Marc Zyngier <[email protected]> wrote:

Interrupt sharing for percpu-devid interrupts is forbidden, and for good reasons. These are interrupts generated *from* a CPU and handled by itself (timer, for example). Nobody in their right mind would put two devices on the same pin (and if they have, they get to keep the pieces...).

But this also prevents more benign cases, where devices are connected to groups of CPUs, and for which the affinities are not overlapping. Effectively, the only thing they share is the interrupt number, and nothing else.

Quoted 8 lines

Let's tweak the definition of IRQF_SHARED applied to percpu_devid interrupts to allow this particular case. This results in extra validation at the point of the interrupt being setup and freed, as well as a tiny bit of extra complexity for interrupts at handling time (to pick the correct irqaction).

#44 lore raw

Re: [PATCH v4 16/26] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

In reply to Marc Zyngier
Quoted 11 lines · Marc Zyngier

Interrupt sharing for percpu-devid interrupts is forbidden, and for good reasons. These are interrupts generated *from* a CPU and handled by itself (timer, for example). Nobody in their right mind would put two devices on the same pin (and if they have, they get to keep the pieces...).

But this also prevents more benign cases, where devices are connected to groups of CPUs, and for which the affinities are not overlapping. Effectively, the only thing they share is the interrupt number, and nothing else.

Quoted 8 lines

Let's tweak the definition of IRQF_SHARED applied to percpu_devid interrupts to allow this particular case. This results in extra validation at the point of the interrupt being setup and freed, as well as a tiny bit of extra complexity for interrupts at handling time (to pick the correct irqaction).

I picked up this patch via linux-next and it appears be causing boot regressions on MIPS/qemu. This patch was identified with a bisect and a git revert of this patch from the linux-next tip resolves the problem (specifically, next-20251204 with git revert bdf4e2ac295f).

I'm running the code as part of the kgdb test suite but the system doesn't survive long enough for kgdb to be involved. In fact I was able to reduce things to the following reproduction with all the kgdb pieces removed:

    make malta_kvm_defconfig generic/64r6.config
    ../scripts/config \
        --enable WERROR --enable CPU_MIPS64_R6 --enable MIPS_CPS \
	--enable BLK_DEV_INITRD --set-val FRAME_WARN 2048
    make olddefconfig
    make -j$(nproc) all
    qemu-system-mips64el -cpu I6400 -M malta -m 1G -smp 2 \
        -kernel vmlinux -nographic \
	-append " console=ttyS0,115200 clk_ignore_unused"

The stack dumps continually so I have to abridge the logs but the logs to second stack trace are:

~~~
Linux version 6.18.0-next-20251204 (drt@wychelm) (mips64el-linux-gcc.br_real (Buildroot 2025.02.8) 14.3.0, GNU ld (GNU Binutils) 2.44) #20 SMP Thu Dec 4 10:37:28 GMT 2025
earlycon: uart8250 at I/O port 0x3f8 (options '38400n8')
printk: legacy bootconsole [uart8250] enabled
CPU0 revision is: 0001a900 (MIPS I6400)
FPU revision is: 20f30300
MSA revision is: 00000300
MIPS: machine is mti,malta
Software DMA cache coherency enabled
Initial ramdisk at: 0x900000000fc40000 (3818338 bytes)
OF: reserved mem: Reserved memory: No reserved-memory node in the DT
VP topology {2} total 2
Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 bytes
Zone ranges:

  DMA      [mem 0x0000000000000000-0x0000000000ffffff]
  DMA32    [mem 0x0000000001000000-0x00000000ffffffff]
  Normal   empty

Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000000000000-0x000000000fffffff]
node 0: [mem 0x0000000090000000-0x00000000bfffffff]
Initmem setup node 0 [mem 0x0000000000000000-0x00000000bfffffff]
On node 0, zone DMA32: 131072 pages in unavailable ranges
random: crng init done
percpu: Embedded 7 pages/cpu s69728 r8192 d36768 u114688
Kernel command line: rd_start=0xffffffff8fc40000 rd_size=3818338 console=ttyS0,115200 kgdboc=ttyS0 clk_ignore_unused Unknown kernel command line parameters "kgdboc=ttyS0", will be passed to user space.
printk: log buffer data + meta data: 32768 + 114688 = 147456 bytes
Dentry cache hash table entries: 131072 (order: 6, 1048576 bytes, linear)
Inode-cache hash table entries: 65536 (order: 5, 524288 bytes, linear)
Cache parity protection disabled
MAAR configuration:
[0]: 0x0000000000000000-0x000000000fffffff speculate
[1]: 0x0000000090000000-0x00000000bfffffff speculate
[2]: disabled
[3]: disabled
[4]: disabled
[5]: disabled
[6]: disabled
[7]: disabled
Built 1 zonelists, mobility grouping on. Total pages: 65536
mem auto-init: stack:all(zero), heap alloc:off, heap free:off
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
rcu: Hierarchical RCU implementation.
rcu: RCU event tracing is enabled.
Tracing variant of Tasks RCU enabled.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
RCU Tasks Trace: Setting shift to 1 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=2.
NR_IRQS: 256
rcu: srcu_init: Setting srcu_struct sizes based on contention.
CPU frequency 320.00 MHz
GIC frequency 100.00 MHz
clocksource: GIC: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19113045595 ns
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21475332090ns
clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 11945377117 ns
Console: colour dummy device 80x25
Calibrating delay loop...
CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff801c2398, ra == ffffffff801bab00 Oops[#1]:

CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.18.0-next-20251204 #20 NONE
Hardware name: mti,malta
$ 0   : 0000000000000000 0000000000000001 0000000000000000 0000000000000000
$ 4   : 0000000000000001 a8000000020e8008 0000000000000000 ffffffff80c23b80
$ 8   : 0000000000000004 0000000000000000 0000000000000000 000000000000002f
$12   : a8000000020f4000 0000000000003ff0 0000000000003000 0000000000000003
$16   : ffffffff80d095c0 ffffffff80ceb410 0000000000000019 ffffffff80c378c0
$20   : ffffffff80c4bec8 0000000000000000 ffffffff80e00000 ffffffff80de0000
$24   : 0000000000000000 0000000000000010
$28   : ffffffff80c20000 a8000000020f7ec0 a800000000e12fcd ffffffff801bab00
epc   : ffffffff801c2398 handle_percpu_devid_irq+0xb8/0x250
ra    : ffffffff801bab00 handle_irq_desc+0x48/0x88
Status: 1400a4e2	KX SX UX KERNEL EXL
Cause : 00800408 (ExcCode 02)
BadVA : 0000000000000000
PrId  : 0001a900 (MIPS I6400)
Modules linked in:
Process swapper/0 (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
Stack : ffffffff80c35a2c 0000000000000002 ffffffff80e00000 0fffffffffffffff
        ffffffff80c50000 0000000000000001 0000000000000003 ffffffff801bab00
        0000000000000000 ffffffff805d82a8 0000000000000000 0000000000000008
        0000000000000000 0000000000000000 0000000000000000 5189d95a7a4f4800
        a800000002014300 0000000000000002 0000000000000001 000000000000001f
        ffffffff80e00000 0000000000000004 0000000000000000 ffffffff801bab00
        0000000000000000 ffffffff809ec128 0000000000000001 fffffffffffffffb
        0000000000000001 ffffffff805d7ebc 0000000000000000 0000000000000000
        ffffffff80c23c80 ffffffff80c50000 ffffffff80de0000 ffffffff80db0000
        0000000000000000 ffffffff80112f10 ffffffff80c23c80 0000000000000000
Call Trace:
[<ffffffff801c2398>] handle_percpu_devid_irq+0xb8/0x250
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff805d82a8>] gic_irq_dispatch+0xc0/0x288
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff809ec128>] do_domain_IRQ+0x28/0x40
[<ffffffff805d7ebc>] plat_irq_dispatch+0x64/0xe8
[<ffffffff80112f10>] handle_int+0x134/0x140
[<ffffffff80110dc8>] calibrate_delay+0x158/0x290
[<ffffffff80d58e48>] start_kernel+0x754/0x7a4
Code: da000048  de020010  0043102d <dc420000> 00c21016  30420001  d85ffff8  00000000  00000000

CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff801c2398, ra == ffffffff801bab00 Oops[#2]:

CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Tainted: G      D             6.18.0-next-20251204 #20 NONE
Tainted: [D]=DIE
Hardware name: mti,malta
$ 0   : 0000000000000000 0000000000000001 0000000000000000 0000000000000000
$ 4   : 0000000000000002 a8000000020e8008 0000000000000000 a8000000020f7ae0
$ 8   : 0000000000000004 0000000000000000 0000000000000000 0000000000000000
$12   : a8000000020f4000 a8000000020f4000 0000000000003000 0000000000000000
$16   : ffffffff80d095c0 ffffffff80ceb410 0000000000000019 ffffffff80c378c0
$20   : ffffffff80c4bec8 0000000000000000 ffffffff80e00000 0000000000000001
$24   : 0000000000000000 ffffffffffffffff
$28   : ffffffff80c20000 a8000000020f7ab0 a800000000e12fcd ffffffff801bab00
epc   : ffffffff801c2398 handle_percpu_devid_irq+0xb8/0x250
ra    : ffffffff801bab00 handle_irq_desc+0x48/0x88
Status: 1400a4e2	KX SX UX KERNEL EXL
Cause : 00800408 (ExcCode 02)
BadVA : 0000000000000000
PrId  : 0001a900 (MIPS I6400)
Modules linked in:
Process swapper/0 (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
Stack : ffffffff80c50000 0000000000000002 ffffffff80e00000 0fffffffffffffff
        ffffffff80c50000 0000000000000001 0000000000000003 ffffffff801bab00
        0000000000000000 ffffffff805d82a8 a8000000020f7bd8 ffffffff801b94f4
        0000000000000000 0000000000000000 ffffffff80c4bc10 5189d95a7a4f4800
        a800000002014300 0000000000000002 0000000000000001 000000000000001f
        ffffffff80e00000 0000000000000004 0000000000000000 ffffffff801bab00
        0000000000000001 ffffffff809ec128 0000000000000000 fffffffffffffffb
        0000000000000001 ffffffff805d7ebc ffffffff80c7b558 ffffffff80c23c80
        a8000000020f7be0 ffffffff80b2fcb8 ffffffff80de0000 ffffffff80c4bec8
        ffffffff80c515c0 ffffffff80112f10 0000000000000000 0000000000000001
        ...
Call Trace:
[<ffffffff801c2398>] handle_percpu_devid_irq+0xb8/0x250
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff805d82a8>] gic_irq_dispatch+0xc0/0x288
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff809ec128>] do_domain_IRQ+0x28/0x40
[<ffffffff805d7ebc>] plat_irq_dispatch+0x64/0xe8
[<ffffffff80112f10>] handle_int+0x134/0x140
[<ffffffff8011a730>] die+0xa8/0xf8
[<ffffffff80134680>] do_page_fault+0x530/0x540
[<ffffffff8013a1a8>] tlb_do_page_fault_0+0x108/0x110
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
Code: da000048  de020010  0043102d <dc420000> 00c21016  30420001  d85ffff8  00000000  00000000

~~~

FWIW I'm using a buildroot gcc-14 toolchain but I've seen the same problem on gcc-13 in previous kgdbtest logs.

Daniel.

author maintainer
#45 lore raw

Re: [PATCH v4 16/26] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

Quoted 32 lines · Daniel Thompson
Quoted 11 lines · Marc Zyngier

Interrupt sharing for percpu-devid interrupts is forbidden, and for good reasons. These are interrupts generated *from* a CPU and handled by itself (timer, for example). Nobody in their right mind would put two devices on the same pin (and if they have, they get to keep the pieces...).

But this also prevents more benign cases, where devices are connected to groups of CPUs, and for which the affinities are not overlapping. Effectively, the only thing they share is the interrupt number, and nothing else.

Quoted 8 lines

Let's tweak the definition of IRQF_SHARED applied to percpu_devid interrupts to allow this particular case. This results in extra validation at the point of the interrupt being setup and freed, as well as a tiny bit of extra complexity for interrupts at handling time (to pick the correct irqaction).

I picked up this patch via linux-next and it appears be causing boot regressions on MIPS/qemu. This patch was identified with a bisect and a git revert of this patch from the linux-next tip resolves the problem (specifically, next-20251204 with git revert bdf4e2ac295f).

I'm running the code as part of the kgdb test suite but the system doesn't survive long enough for kgdb to be involved. In fact I was able to reduce things to the following reproduction with all the kgdb pieces removed:

Quoted 9 lines
    make malta_kvm_defconfig generic/64r6.config
    ../scripts/config \
        --enable WERROR --enable CPU_MIPS64_R6 --enable MIPS_CPS \
	--enable BLK_DEV_INITRD --set-val FRAME_WARN 2048
    make olddefconfig
    make -j$(nproc) all
    qemu-system-mips64el -cpu I6400 -M malta -m 1G -smp 2 \
        -kernel vmlinux -nographic \
	-append " console=ttyS0,115200 clk_ignore_unused"

Many thanks for the minimal reproducer, that really helped a lot!

[...]

Quoted 32 lines

CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff801c2398, ra == ffffffff801bab00 Oops[#1]:

CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.18.0-next-20251204 #20 NONE
Hardware name: mti,malta
$ 0   : 0000000000000000 0000000000000001 0000000000000000 0000000000000000
$ 4   : 0000000000000001 a8000000020e8008 0000000000000000 ffffffff80c23b80
$ 8   : 0000000000000004 0000000000000000 0000000000000000 000000000000002f
$12   : a8000000020f4000 0000000000003ff0 0000000000003000 0000000000000003
$16   : ffffffff80d095c0 ffffffff80ceb410 0000000000000019 ffffffff80c378c0
$20   : ffffffff80c4bec8 0000000000000000 ffffffff80e00000 ffffffff80de0000
$24   : 0000000000000000 0000000000000010
$28   : ffffffff80c20000 a8000000020f7ec0 a800000000e12fcd ffffffff801bab00
epc   : ffffffff801c2398 handle_percpu_devid_irq+0xb8/0x250
ra    : ffffffff801bab00 handle_irq_desc+0x48/0x88
Status: 1400a4e2	KX SX UX KERNEL EXL
Cause : 00800408 (ExcCode 02)
BadVA : 0000000000000000
PrId  : 0001a900 (MIPS I6400)
Modules linked in:
Process swapper/0 (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
Stack : ffffffff80c35a2c 0000000000000002 ffffffff80e00000 0fffffffffffffff
        ffffffff80c50000 0000000000000001 0000000000000003 ffffffff801bab00
        0000000000000000 ffffffff805d82a8 0000000000000000 0000000000000008
        0000000000000000 0000000000000000 0000000000000000 5189d95a7a4f4800
        a800000002014300 0000000000000002 0000000000000001 000000000000001f
        ffffffff80e00000 0000000000000004 0000000000000000 ffffffff801bab00
        0000000000000000 ffffffff809ec128 0000000000000001 fffffffffffffffb
        0000000000000001 ffffffff805d7ebc 0000000000000000 0000000000000000
        ffffffff80c23c80 ffffffff80c50000 ffffffff80de0000 ffffffff80db0000
        0000000000000000 ffffffff80112f10 ffffffff80c23c80 0000000000000000
Call Trace:
[<ffffffff801c2398>] handle_percpu_devid_irq+0xb8/0x250
Quoted 8 lines
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff805d82a8>] gic_irq_dispatch+0xc0/0x288
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff809ec128>] do_domain_IRQ+0x28/0x40
[<ffffffff805d7ebc>] plat_irq_dispatch+0x64/0xe8
[<ffffffff80112f10>] handle_int+0x134/0x140
[<ffffffff80110dc8>] calibrate_delay+0x158/0x290
[<ffffffff80d58e48>] start_kernel+0x754/0x7a4

This hack fixes it for me, but really, mips needs to grow up and stop using these antiquated APIs.

Can please you give it a go?

Thanks,

	M.
kernel/irq/manage.c +3 -0
index 0bb29316b4362..8b1b4c8a4f54c 100644
@@ -2470,6 +2470,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 	if (retval < 0)
 		return retval;
 
+	if (!act->affinity)
+		act->affinity = cpu_online_mask;
+
 	retval = __setup_irq(irq, desc, act);
 
 	if (retval)
Signature · 1 line
Without deviation from the norm, progress is not possible.
#46 lore raw

Re: [PATCH v4 16/26] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

Quoted 43 lines · Marc Zyngier
Quoted 32 lines · Daniel Thompson

CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff801c2398, ra == ffffffff801bab00 Oops[#1]:

CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.18.0-next-20251204 #20 NONE
Hardware name: mti,malta
$ 0   : 0000000000000000 0000000000000001 0000000000000000 0000000000000000
$ 4   : 0000000000000001 a8000000020e8008 0000000000000000 ffffffff80c23b80
$ 8   : 0000000000000004 0000000000000000 0000000000000000 000000000000002f
$12   : a8000000020f4000 0000000000003ff0 0000000000003000 0000000000000003
$16   : ffffffff80d095c0 ffffffff80ceb410 0000000000000019 ffffffff80c378c0
$20   : ffffffff80c4bec8 0000000000000000 ffffffff80e00000 ffffffff80de0000
$24   : 0000000000000000 0000000000000010
$28   : ffffffff80c20000 a8000000020f7ec0 a800000000e12fcd ffffffff801bab00
epc   : ffffffff801c2398 handle_percpu_devid_irq+0xb8/0x250
ra    : ffffffff801bab00 handle_irq_desc+0x48/0x88
Status: 1400a4e2	KX SX UX KERNEL EXL
Cause : 00800408 (ExcCode 02)
BadVA : 0000000000000000
PrId  : 0001a900 (MIPS I6400)
Modules linked in:
Process swapper/0 (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
Stack : ffffffff80c35a2c 0000000000000002 ffffffff80e00000 0fffffffffffffff
        ffffffff80c50000 0000000000000001 0000000000000003 ffffffff801bab00
        0000000000000000 ffffffff805d82a8 0000000000000000 0000000000000008
        0000000000000000 0000000000000000 0000000000000000 5189d95a7a4f4800
        a800000002014300 0000000000000002 0000000000000001 000000000000001f
        ffffffff80e00000 0000000000000004 0000000000000000 ffffffff801bab00
        0000000000000000 ffffffff809ec128 0000000000000001 fffffffffffffffb
        0000000000000001 ffffffff805d7ebc 0000000000000000 0000000000000000
        ffffffff80c23c80 ffffffff80c50000 ffffffff80de0000 ffffffff80db0000
        0000000000000000 ffffffff80112f10 ffffffff80c23c80 0000000000000000
Call Trace:
[<ffffffff801c2398>] handle_percpu_devid_irq+0xb8/0x250
Quoted 8 lines
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff805d82a8>] gic_irq_dispatch+0xc0/0x288
[<ffffffff801bab00>] handle_irq_desc+0x48/0x88
[<ffffffff809ec128>] do_domain_IRQ+0x28/0x40
[<ffffffff805d7ebc>] plat_irq_dispatch+0x64/0xe8
[<ffffffff80112f10>] handle_int+0x134/0x140
[<ffffffff80110dc8>] calibrate_delay+0x158/0x290
[<ffffffff80d58e48>] start_kernel+0x754/0x7a4
Quoted 2 lines

This hack fixes it for me, but really, mips needs to grow up and stop using these antiquated APIs.

I can't comment on that. Literally the only thing I ever do on MIPS is test kgdb ;-) .

Quoted 1 line

Can please you give it a go?

Looks good to me.

Local testing on MIPS worked nicely and I got a successful build back for the kgdb tests:
https://gitlab.com/daniel-thompson/linux/-/pipelines/2196473049

Daniel.

author maintainer
#47 lore raw

PATCH v4 17/26 genirq: Add request_percpu_irq_affinity() helper

In reply to Marc Zyngier

While it would be nice to simply make request_percpu_irq() take an affinity mask, the churn is likely to be on the irritating side given that most drivers do not give a damn about affinities.

So take the more innocuous path to provide a helper that parallels request_percpu_irq(), with an affinity as a bonus argument.

Yes, request_percpu_irq_affinity() is a bit of a mouthful.

---
 include/linux/interrupt.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/interrupt.h +9 -0
index 81506ab759b81..fa62ab556ee32 100644
@@ -196,6 +196,15 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 				    devname, NULL, percpu_dev_id);
 }
 
+static inline int __must_check
+request_percpu_irq_affinity(unsigned int irq, irq_handler_t handler,
+			    const char *devname, const cpumask_t *affinity,
+			    void __percpu *percpu_dev_id)
+{
+	return __request_percpu_irq(irq, handler, 0,
+				    devname, affinity, percpu_dev_id);
+}
+
 extern int __must_check
 request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
 		   const struct cpumask *affinity, void __percpu *dev_id);
Signature · 1 line
2.47.3
merge bot Applied
#48 lore raw

[tip: irq/core] genirq: Add request_percpu_irq_affinity() helper

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     c734af3b2b95f0ac6ed87c50e7602a6beeaf534f
Gitweb:        https://git.kernel.org/tip/c734af3b2b95f0ac6ed87c50e7602a6beeaf534f
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:34 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:35 +01:00

genirq: Add request_percpu_irq_affinity() helper

While it would be nice to simply make request_percpu_irq() take an affinity mask, the churn is likely to be on the irritating side given that most drivers do not give a damn about affinities.

So take the more innocuous path to provide a helper that parallels request_percpu_irq(), with an affinity as a bonus argument.

Yes, request_percpu_irq_affinity() is a bit of a mouthful.

---
 include/linux/interrupt.h |  9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/interrupt.h +9 -0
index 81506ab..fa62ab5 100644
@@ -196,6 +196,15 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler,
 				    devname, NULL, percpu_dev_id);
 }
 
+static inline int __must_check
+request_percpu_irq_affinity(unsigned int irq, irq_handler_t handler,
+			    const char *devname, const cpumask_t *affinity,
+			    void __percpu *percpu_dev_id)
+{
+	return __request_percpu_irq(irq, handler, 0,
+				    devname, affinity, percpu_dev_id);
+}
+
 extern int __must_check
 request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
 		   const struct cpumask *affinity, void __percpu *dev_id);
Reviewed-by on v4 17/26
#49 lore raw

Re: [PATCH v4 17/26] genirq: Add request_percpu_irq_affinity() helper

In reply to Marc Zyngier
Quoted 3 lines · On Mon, 20 Oct 2025 13:29:34 +0100 Marc Zyngier <[email protected]> wrote:

While it would be nice to simply make request_percpu_irq() take an affinity mask, the churn is likely to be on the irritating side given that most drivers do not give a damn about affinities.

Only 37 instances. I'd have been tempted to do it anyway :)

Quoted 8 lines

So take the more innocuous path to provide a helper that parallels request_percpu_irq(), with an affinity as a bonus argument.

Yes, request_percpu_irq_affinity() is a bit of a mouthful.

author maintainer
#50 lore raw

Re: [PATCH v4 17/26] genirq: Add request_percpu_irq_affinity() helper

Quoted 9 lines · Jonathan Cameron
Quoted 3 lines · On Mon, 20 Oct 2025 13:29:34 +0100 Marc Zyngier <[email protected]> wrote:

While it would be nice to simply make request_percpu_irq() take an affinity mask, the churn is likely to be on the irritating side given that most drivers do not give a damn about affinities.

Only 37 instances. I'd have been tempted to do it anyway :)

I'm leaving this as an exercise for people who enjoy cross-subsystem patch series!

Quoted 10 lines
Quoted 9 lines

So take the more innocuous path to provide a helper that parallels request_percpu_irq(), with an affinity as a bonus argument.

Yes, request_percpu_irq_affinity() is a bit of a mouthful.

Thanks,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
author maintainer
#51 lore raw

PATCH v4 18/26 perf: arm_pmu: Request specific affinities for percpu NMI/IRQ

In reply to Marc Zyngier

From: Will Deacon <[email protected]>

Let the PMU driver request both NMI and normal IRQs with an affinity mask matching the PMU affinity.

---
 drivers/perf/arm_pmu.c          | 44 +++++++++++++++++++--------------
 drivers/perf/arm_pmu_acpi.c     |  2 +-
 drivers/perf/arm_pmu_platform.c |  4 +--
 include/linux/perf/arm_pmu.h    |  4 +--
 4 files changed, 31 insertions(+), 23 deletions(-)
drivers/perf/arm_pmu.c +26 -18
index 22c601b46c858..959ceb3d1f556 100644
@@ -26,7 +26,8 @@
 
 #include <asm/irq_regs.h>
 
-static int armpmu_count_irq_users(const int irq);
+static int armpmu_count_irq_users(const struct cpumask *affinity,
+				  const int irq);
 
 struct pmu_irq_ops {
 	void (*enable_pmuirq)(unsigned int irq);
@@ -64,7 +65,9 @@ static void armpmu_enable_percpu_pmuirq(unsigned int irq)
 static void armpmu_free_percpu_pmuirq(unsigned int irq, int cpu,
 				   void __percpu *devid)
 {
-	if (armpmu_count_irq_users(irq) == 1)
+	struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu);
+
+	if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1)
 		free_percpu_irq(irq, devid);
 }
 
@@ -89,7 +92,9 @@ static void armpmu_disable_percpu_pmunmi(unsigned int irq)
 static void armpmu_free_percpu_pmunmi(unsigned int irq, int cpu,
 				      void __percpu *devid)
 {
-	if (armpmu_count_irq_users(irq) == 1)
+	struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu);
+
+	if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1)
 		free_percpu_nmi(irq, devid);
 }
 
@@ -580,11 +585,11 @@ static const struct attribute_group armpmu_common_attr_group = {
 	.attrs = armpmu_common_attrs,
 };
 
-static int armpmu_count_irq_users(const int irq)
+static int armpmu_count_irq_users(const struct cpumask *affinity, const int irq)
 {
 	int cpu, count = 0;
 
-	for_each_possible_cpu(cpu) {
+	for_each_cpu(cpu, affinity) {
 		if (per_cpu(cpu_irq, cpu) == irq)
 			count++;
 	}
@@ -592,12 +597,13 @@ static int armpmu_count_irq_users(const int irq)
 	return count;
 }
 
-static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq)
+static const struct pmu_irq_ops *
+armpmu_find_irq_ops(const struct cpumask *affinity, int irq)
 {
 	const struct pmu_irq_ops *ops = NULL;
 	int cpu;
 
-	for_each_possible_cpu(cpu) {
+	for_each_cpu(cpu, affinity) {
 		if (per_cpu(cpu_irq, cpu) != irq)
 			continue;
 
@@ -609,22 +615,25 @@ static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq)
 	return ops;
 }
 
-void armpmu_free_irq(int irq, int cpu)
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu)
 {
 	if (per_cpu(cpu_irq, cpu) == 0)
 		return;
 	if (WARN_ON(irq != per_cpu(cpu_irq, cpu)))
 		return;
 
-	per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, &cpu_armpmu);
+	per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, armpmu);
 
 	per_cpu(cpu_irq, cpu) = 0;
 	per_cpu(cpu_irq_ops, cpu) = NULL;
 }
 
-int armpmu_request_irq(int irq, int cpu)
+int armpmu_request_irq(struct arm_pmu * __percpu *pcpu_armpmu, int irq, int cpu)
 {
 	int err = 0;
+	struct arm_pmu **armpmu = per_cpu_ptr(pcpu_armpmu, cpu);
+	const struct cpumask *affinity = *armpmu ? &(*armpmu)->supported_cpus :
+						   cpu_possible_mask; /* ACPI */
 	const irq_handler_t handler = armpmu_dispatch_irq;
 	const struct pmu_irq_ops *irq_ops;
 
@@ -646,25 +655,24 @@ int armpmu_request_irq(int irq, int cpu)
 			    IRQF_NOBALANCING | IRQF_NO_AUTOEN |
 			    IRQF_NO_THREAD;
 
-		err = request_nmi(irq, handler, irq_flags, "arm-pmu",
-				  per_cpu_ptr(&cpu_armpmu, cpu));
+		err = request_nmi(irq, handler, irq_flags, "arm-pmu", armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
 			err = request_irq(irq, handler, irq_flags, "arm-pmu",
-					  per_cpu_ptr(&cpu_armpmu, cpu));
+					  armpmu);
 			irq_ops = &pmuirq_ops;
 		} else {
 			has_nmi = true;
 			irq_ops = &pmunmi_ops;
 		}
-	} else if (armpmu_count_irq_users(irq) == 0) {
-		err = request_percpu_nmi(irq, handler, "arm-pmu", NULL, &cpu_armpmu);
+	} else if (armpmu_count_irq_users(affinity, irq) == 0) {
+		err = request_percpu_nmi(irq, handler, "arm-pmu", affinity, pcpu_armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
-			err = request_percpu_irq(irq, handler, "arm-pmu",
-						 &cpu_armpmu);
+			err = request_percpu_irq_affinity(irq, handler, "arm-pmu",
+							  affinity, pcpu_armpmu);
 			irq_ops = &percpu_pmuirq_ops;
 		} else {
 			has_nmi = true;
@@ -672,7 +680,7 @@ int armpmu_request_irq(int irq, int cpu)
 		}
 	} else {
 		/* Per cpudevid irq was already requested by another CPU */
-		irq_ops = armpmu_find_irq_ops(irq);
+		irq_ops = armpmu_find_irq_ops(affinity, irq);
 
 		if (WARN_ON(!irq_ops))
 			err = -EINVAL;
drivers/perf/arm_pmu_acpi.c +1 -1
index 05dda19c5359a..e80f76d95e68b 100644
@@ -218,7 +218,7 @@ static int arm_pmu_acpi_parse_irqs(void)
 		 * them with their PMUs.
 		 */
 		per_cpu(pmu_irqs, cpu) = irq;
-		err = armpmu_request_irq(irq, cpu);
+		err = armpmu_request_irq(&probed_pmus, irq, cpu);
 		if (err)
 			goto out_err;
 	}
drivers/perf/arm_pmu_platform.c +2 -2
index 9c0494d8a867a..1c9e50a132015 100644
@@ -165,7 +165,7 @@ static int armpmu_request_irqs(struct arm_pmu *armpmu)
 		if (!irq)
 			continue;
 
-		err = armpmu_request_irq(irq, cpu);
+		err = armpmu_request_irq(&hw_events->percpu_pmu, irq, cpu);
 		if (err)
 			break;
 	}
@@ -181,7 +181,7 @@ static void armpmu_free_irqs(struct arm_pmu *armpmu)
 	for_each_cpu(cpu, &armpmu->supported_cpus) {
 		int irq = per_cpu(hw_events->irq, cpu);
 
-		armpmu_free_irq(irq, cpu);
+		armpmu_free_irq(&hw_events->percpu_pmu, irq, cpu);
 	}
 }
 
include/linux/perf/arm_pmu.h +2 -2
index 93c9a26492fcf..6690bd77aa4ee 100644
@@ -190,8 +190,8 @@ bool arm_pmu_irq_is_nmi(void);
 struct arm_pmu *armpmu_alloc(void);
 void armpmu_free(struct arm_pmu *pmu);
 int armpmu_register(struct arm_pmu *pmu);
-int armpmu_request_irq(int irq, int cpu);
-void armpmu_free_irq(int irq, int cpu);
+int armpmu_request_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);
 
 #define ARMV8_PMU_PDEV_NAME "armv8-pmu"
 
Signature · 1 line
2.47.3
merge bot Applied
#52 lore raw

[tip: irq/core] perf: arm_pmu: Request specific affinities for per CPU NMIs/interrupts

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     54b350fa8e965dc59622698e2a18d6bf73944bf4
Gitweb:        https://git.kernel.org/tip/54b350fa8e965dc59622698e2a18d6bf73944bf4
Author:        Will Deacon <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:35 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:35 +01:00

perf: arm_pmu: Request specific affinities for per CPU NMIs/interrupts

Let the PMU driver request both NMIs and normal interrupts with an affinity mask matching the PMU affinity.

---
 drivers/perf/arm_pmu.c          | 44 ++++++++++++++++++--------------
 drivers/perf/arm_pmu_acpi.c     |  2 +-
 drivers/perf/arm_pmu_platform.c |  4 +--
 include/linux/perf/arm_pmu.h    |  4 +--
 4 files changed, 31 insertions(+), 23 deletions(-)
drivers/perf/arm_pmu.c +26 -18
index 22c601b..959ceb3 100644
@@ -26,7 +26,8 @@
 
 #include <asm/irq_regs.h>
 
-static int armpmu_count_irq_users(const int irq);
+static int armpmu_count_irq_users(const struct cpumask *affinity,
+				  const int irq);
 
 struct pmu_irq_ops {
 	void (*enable_pmuirq)(unsigned int irq);
@@ -64,7 +65,9 @@ static void armpmu_enable_percpu_pmuirq(unsigned int irq)
 static void armpmu_free_percpu_pmuirq(unsigned int irq, int cpu,
 				   void __percpu *devid)
 {
-	if (armpmu_count_irq_users(irq) == 1)
+	struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu);
+
+	if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1)
 		free_percpu_irq(irq, devid);
 }
 
@@ -89,7 +92,9 @@ static void armpmu_disable_percpu_pmunmi(unsigned int irq)
 static void armpmu_free_percpu_pmunmi(unsigned int irq, int cpu,
 				      void __percpu *devid)
 {
-	if (armpmu_count_irq_users(irq) == 1)
+	struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu);
+
+	if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1)
 		free_percpu_nmi(irq, devid);
 }
 
@@ -580,11 +585,11 @@ static const struct attribute_group armpmu_common_attr_group = {
 	.attrs = armpmu_common_attrs,
 };
 
-static int armpmu_count_irq_users(const int irq)
+static int armpmu_count_irq_users(const struct cpumask *affinity, const int irq)
 {
 	int cpu, count = 0;
 
-	for_each_possible_cpu(cpu) {
+	for_each_cpu(cpu, affinity) {
 		if (per_cpu(cpu_irq, cpu) == irq)
 			count++;
 	}
@@ -592,12 +597,13 @@ static int armpmu_count_irq_users(const int irq)
 	return count;
 }
 
-static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq)
+static const struct pmu_irq_ops *
+armpmu_find_irq_ops(const struct cpumask *affinity, int irq)
 {
 	const struct pmu_irq_ops *ops = NULL;
 	int cpu;
 
-	for_each_possible_cpu(cpu) {
+	for_each_cpu(cpu, affinity) {
 		if (per_cpu(cpu_irq, cpu) != irq)
 			continue;
 
@@ -609,22 +615,25 @@ static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq)
 	return ops;
 }
 
-void armpmu_free_irq(int irq, int cpu)
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu)
 {
 	if (per_cpu(cpu_irq, cpu) == 0)
 		return;
 	if (WARN_ON(irq != per_cpu(cpu_irq, cpu)))
 		return;
 
-	per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, &cpu_armpmu);
+	per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, armpmu);
 
 	per_cpu(cpu_irq, cpu) = 0;
 	per_cpu(cpu_irq_ops, cpu) = NULL;
 }
 
-int armpmu_request_irq(int irq, int cpu)
+int armpmu_request_irq(struct arm_pmu * __percpu *pcpu_armpmu, int irq, int cpu)
 {
 	int err = 0;
+	struct arm_pmu **armpmu = per_cpu_ptr(pcpu_armpmu, cpu);
+	const struct cpumask *affinity = *armpmu ? &(*armpmu)->supported_cpus :
+						   cpu_possible_mask; /* ACPI */
 	const irq_handler_t handler = armpmu_dispatch_irq;
 	const struct pmu_irq_ops *irq_ops;
 
@@ -646,25 +655,24 @@ int armpmu_request_irq(int irq, int cpu)
 			    IRQF_NOBALANCING | IRQF_NO_AUTOEN |
 			    IRQF_NO_THREAD;
 
-		err = request_nmi(irq, handler, irq_flags, "arm-pmu",
-				  per_cpu_ptr(&cpu_armpmu, cpu));
+		err = request_nmi(irq, handler, irq_flags, "arm-pmu", armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
 			err = request_irq(irq, handler, irq_flags, "arm-pmu",
-					  per_cpu_ptr(&cpu_armpmu, cpu));
+					  armpmu);
 			irq_ops = &pmuirq_ops;
 		} else {
 			has_nmi = true;
 			irq_ops = &pmunmi_ops;
 		}
-	} else if (armpmu_count_irq_users(irq) == 0) {
-		err = request_percpu_nmi(irq, handler, "arm-pmu", NULL, &cpu_armpmu);
+	} else if (armpmu_count_irq_users(affinity, irq) == 0) {
+		err = request_percpu_nmi(irq, handler, "arm-pmu", affinity, pcpu_armpmu);
 
 		/* If cannot get an NMI, get a normal interrupt */
 		if (err) {
-			err = request_percpu_irq(irq, handler, "arm-pmu",
-						 &cpu_armpmu);
+			err = request_percpu_irq_affinity(irq, handler, "arm-pmu",
+							  affinity, pcpu_armpmu);
 			irq_ops = &percpu_pmuirq_ops;
 		} else {
 			has_nmi = true;
@@ -672,7 +680,7 @@ int armpmu_request_irq(int irq, int cpu)
 		}
 	} else {
 		/* Per cpudevid irq was already requested by another CPU */
-		irq_ops = armpmu_find_irq_ops(irq);
+		irq_ops = armpmu_find_irq_ops(affinity, irq);
 
 		if (WARN_ON(!irq_ops))
 			err = -EINVAL;
drivers/perf/arm_pmu_acpi.c +1 -1
index 05dda19..e80f76d 100644
@@ -218,7 +218,7 @@ static int arm_pmu_acpi_parse_irqs(void)
 		 * them with their PMUs.
 		 */
 		per_cpu(pmu_irqs, cpu) = irq;
-		err = armpmu_request_irq(irq, cpu);
+		err = armpmu_request_irq(&probed_pmus, irq, cpu);
 		if (err)
 			goto out_err;
 	}
drivers/perf/arm_pmu_platform.c +2 -2
index 9c0494d..1c9e50a 100644
@@ -165,7 +165,7 @@ static int armpmu_request_irqs(struct arm_pmu *armpmu)
 		if (!irq)
 			continue;
 
-		err = armpmu_request_irq(irq, cpu);
+		err = armpmu_request_irq(&hw_events->percpu_pmu, irq, cpu);
 		if (err)
 			break;
 	}
@@ -181,7 +181,7 @@ static void armpmu_free_irqs(struct arm_pmu *armpmu)
 	for_each_cpu(cpu, &armpmu->supported_cpus) {
 		int irq = per_cpu(hw_events->irq, cpu);
 
-		armpmu_free_irq(irq, cpu);
+		armpmu_free_irq(&hw_events->percpu_pmu, irq, cpu);
 	}
 }
 
include/linux/perf/arm_pmu.h +2 -2
index 93c9a26..6690bd7 100644
@@ -190,8 +190,8 @@ bool arm_pmu_irq_is_nmi(void);
 struct arm_pmu *armpmu_alloc(void);
 void armpmu_free(struct arm_pmu *pmu);
 int armpmu_register(struct arm_pmu *pmu);
-int armpmu_request_irq(int irq, int cpu);
-void armpmu_free_irq(int irq, int cpu);
+int armpmu_request_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);
 
 #define ARMV8_PMU_PDEV_NAME "armv8-pmu"
 
Reviewed-by on v4 18/26
#53 lore raw

Re: [PATCH v4 18/26] perf: arm_pmu: Request specific affinities for percpu NMI/IRQ

In reply to Marc Zyngier
Quoted 8 lines · On Mon, 20 Oct 2025 13:29:35 +0100 Marc Zyngier <[email protected]> wrote:

From: Will Deacon <[email protected]>

Let the PMU driver request both NMI and normal IRQs with an affinity mask matching the PMU affinity.

author maintainer
#54 lore raw

PATCH v4 19/26 perf: arm_spe_pmu: Request specific affinities for percpu IRQ

In reply to Marc Zyngier

Let the SPE driver request IRQs with an affinity mask matching the SPE implementation affinity.

---
 drivers/perf/arm_spe_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/arm_spe_pmu.c +2 -2
index 1460b02d20e8b..87908f0712c0c 100644
@@ -1259,8 +1259,8 @@ static int arm_spe_pmu_dev_init(struct arm_spe_pmu *spe_pmu)
 		return -ENXIO;
 
 	/* Request our PPIs (note that the IRQ is still disabled) */
-	ret = request_percpu_irq(spe_pmu->irq, arm_spe_pmu_irq_handler, DRVNAME,
-				 spe_pmu->handle);
+	ret = request_percpu_irq_affinity(spe_pmu->irq, arm_spe_pmu_irq_handler,
+					  DRVNAME, mask, spe_pmu->handle);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.47.3
merge bot Applied
#55 lore raw

[tip: irq/core] perf: arm_spe_pmu: Request specific affinities for per CPU interrupts

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     f8112d29ba992e51e4789844340f7da4bdca5fcb
Gitweb:        https://git.kernel.org/tip/f8112d29ba992e51e4789844340f7da4bdca5fcb
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:36 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:36 +01:00

perf: arm_spe_pmu: Request specific affinities for per CPU interrupts

Let the SPE driver request interrupts with an affinity mask matching the SPE implementation affinity.

---
 drivers/perf/arm_spe_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/arm_spe_pmu.c +2 -2
index 1460b02..87908f0 100644
@@ -1259,8 +1259,8 @@ static int arm_spe_pmu_dev_init(struct arm_spe_pmu *spe_pmu)
 		return -ENXIO;
 
 	/* Request our PPIs (note that the IRQ is still disabled) */
-	ret = request_percpu_irq(spe_pmu->irq, arm_spe_pmu_irq_handler, DRVNAME,
-				 spe_pmu->handle);
+	ret = request_percpu_irq_affinity(spe_pmu->irq, arm_spe_pmu_irq_handler,
+					  DRVNAME, mask, spe_pmu->handle);
 	if (ret)
 		return ret;
 
Reviewed-by on v4 19/26
#56 lore raw

Re: [PATCH v4 19/26] perf: arm_spe_pmu: Request specific affinities for percpu IRQ

In reply to Marc Zyngier
Quoted 5 lines · On Mon, 20 Oct 2025 13:29:36 +0100 Marc Zyngier <[email protected]> wrote:

Let the SPE driver request IRQs with an affinity mask matching the SPE implementation affinity.

Quoted 19 lines
---
 drivers/perf/arm_spe_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/arm_spe_pmu.c +2 -2
index 1460b02d20e8b..87908f0712c0c 100644
@@ -1259,8 +1259,8 @@ static int arm_spe_pmu_dev_init(struct arm_spe_pmu *spe_pmu)
 		return -ENXIO;
 
 	/* Request our PPIs (note that the IRQ is still disabled) */
-	ret = request_percpu_irq(spe_pmu->irq, arm_spe_pmu_irq_handler, DRVNAME,
-				 spe_pmu->handle);
+	ret = request_percpu_irq_affinity(spe_pmu->irq, arm_spe_pmu_irq_handler,
+					  DRVNAME, mask, spe_pmu->handle);
 	if (ret)
 		return ret;
 
author maintainer
#57 lore raw

PATCH v4 20/26 coresight: trbe: Request specific affinities for percpu IRQ

In reply to Marc Zyngier

Let the TRBE driver request IRQs with an affinity mask matching the TRBE implementation affinity.

---
 drivers/hwtracing/coresight/coresight-trbe.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/hwtracing/coresight/coresight-trbe.c +2 -1
index 8f17160fec442..9f64f463339d6 100644
@@ -1494,7 +1494,8 @@ static int arm_trbe_probe_irq(struct platform_device *pdev,
 	if (!drvdata->handle)
 		return -ENOMEM;
 
-	ret = request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle);
+	ret = request_percpu_irq_affinity(drvdata->irq, arm_trbe_irq_handler, DRVNAME,
+					  affinity, drvdata->handle);
 	if (ret) {
 		free_percpu(drvdata->handle);
 		return ret;
Signature · 1 line
2.47.3
merge bot Applied
#58 lore raw

[tip: irq/core] coresight: trbe: Request specific affinities for per CPU interrupts

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     4cdf4813f528cdadfc3778fed6b7783cfe1eb75a
Gitweb:        https://git.kernel.org/tip/4cdf4813f528cdadfc3778fed6b7783cfe1eb75a
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:37 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:36 +01:00

coresight: trbe: Request specific affinities for per CPU interrupts

Let the TRBE driver request interrupts with an affinity mask matching the TRBE implementation affinity.

---
 drivers/hwtracing/coresight/coresight-trbe.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/hwtracing/coresight/coresight-trbe.c +2 -1
index 8f17160..9f64f46 100644
@@ -1494,7 +1494,8 @@ static int arm_trbe_probe_irq(struct platform_device *pdev,
 	if (!drvdata->handle)
 		return -ENOMEM;
 
-	ret = request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle);
+	ret = request_percpu_irq_affinity(drvdata->irq, arm_trbe_irq_handler, DRVNAME,
+					  affinity, drvdata->handle);
 	if (ret) {
 		free_percpu(drvdata->handle);
 		return ret;
Reviewed-by on v4 20/26
#59 lore raw

Re: [PATCH v4 20/26] coresight: trbe: Request specific affinities for percpu IRQ

In reply to Marc Zyngier
Quoted 6 lines · On Mon, 20 Oct 2025 13:29:37 +0100 Marc Zyngier <[email protected]> wrote:

Let the TRBE driver request IRQs with an affinity mask matching the TRBE implementation affinity.

FWIW given how simple this is.

author maintainer
#60 lore raw

PATCH v4 21/26 irqchip/gic-v3: Drop support for custom PPI partitions

In reply to Marc Zyngier

The only thing getting in the way of correctly handling PPIs the way they were intended is the GICv3 hack that deals with PPI partitions.

Remove that code, allowing the common code to kick in.

---
 drivers/irqchip/Kconfig      |   1 -
 drivers/irqchip/irq-gic-v3.c | 133 +++--------------------------------
 2 files changed, 8 insertions(+), 126 deletions(-)
drivers/irqchip/Kconfig +0 -1
index a61c6dc63c29c..648b3618fc784 100644
@@ -36,7 +36,6 @@ config GIC_NON_BANKED
 config ARM_GIC_V3
 	bool
 	select IRQ_DOMAIN_HIERARCHY
-	select PARTITION_PERCPU
 	select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 	select HAVE_ARM_SMCCC_DISCOVERY
 	select IRQ_MSI_IOMMU
drivers/irqchip/irq-gic-v3.c +8 -125

210 lines not on this page · raw message

Signature · 1 line
2.47.3
merge bot Applied
#61 lore raw

[tip: irq/core] irqchip/gic-v3: Drop support for custom PPI partitions

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     64b9738eaa937232f2567fd55bbb4fc1a00242ea
Gitweb:        https://git.kernel.org/tip/64b9738eaa937232f2567fd55bbb4fc1a00242ea
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:38 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:36 +01:00

irqchip/gic-v3: Drop support for custom PPI partitions

The only thing getting in the way of correctly handling PPIs the way they were intended is the GICv3 hack that deals with PPI partitions.

Remove that code, allowing the common code to kick in.

---
 drivers/irqchip/Kconfig      |   1 +-
 drivers/irqchip/irq-gic-v3.c | 133 ++--------------------------------
 2 files changed, 8 insertions(+), 126 deletions(-)
drivers/irqchip/Kconfig +0 -1
index a61c6dc..648b361 100644
@@ -36,7 +36,6 @@ config GIC_NON_BANKED
 config ARM_GIC_V3
 	bool
 	select IRQ_DOMAIN_HIERARCHY
-	select PARTITION_PERCPU
 	select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 	select HAVE_ARM_SMCCC_DISCOVERY
 	select IRQ_MSI_IOMMU
drivers/irqchip/irq-gic-v3.c +8 -125

210 lines not on this page · raw message

author maintainer
#62 lore raw

PATCH v4 22/26 irqchip/apple-aic: Drop support for custom PMU irq partitions

In reply to Marc Zyngier

Similarly to what has been done for GICv3, drop the irq partitioning support from the AIC driver, effectively merging the two per-cpu interrupts for the PMU.

---
 drivers/irqchip/irq-apple-aic.c | 28 +++++++---------------------
 1 file changed, 7 insertions(+), 21 deletions(-)
drivers/irqchip/irq-apple-aic.c +7 -21
index cb8b6f40ce8d3..6305d25b9e77b 100644
@@ -578,16 +578,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
 	}
 
 	if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
-			(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
-		int irq;
-		if (cpumask_test_cpu(smp_processor_id(),
-				     &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
-			irq = AIC_CPU_PMU_P;
-		else
-			irq = AIC_CPU_PMU_E;
+			(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT))
 		generic_handle_domain_irq(aic_irqc->hw_domain,
-					  AIC_FIQ_HWIRQ(irq));
-	}
+					  AIC_FIQ_HWIRQ(AIC_CPU_PMU_P));
 
 	if (static_branch_likely(&use_fast_ipi) &&
 	    (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) &&
@@ -632,18 +625,7 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
 				    handle_fasteoi_irq, NULL, NULL);
 		irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
 	} else {
-		int fiq = FIELD_GET(AIC_EVENT_NUM, hw);
-
-		switch (fiq) {
-		case AIC_CPU_PMU_P:
-		case AIC_CPU_PMU_E:
-			irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
-			break;
-		default:
-			irq_set_percpu_devid(irq);
-			break;
-		}
-
+		irq_set_percpu_devid(irq);
 		irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
 				    handle_percpu_devid_irq, NULL, NULL);
 	}
@@ -732,6 +714,10 @@ static int aic_irq_domain_translate(struct irq_domain *id,
 				break;
 			}
 		}
+
+		/* Merge the two PMUs on a single interrupt */
+		if (*hwirq == AIC_CPU_PMU_E)
+			*hwirq = AIC_CPU_PMU_P;
 		break;
 	default:
 		return -EINVAL;
Signature · 1 line
2.47.3
merge bot Applied
#63 lore raw

[tip: irq/core] irqchip/apple-aic: Drop support for custom PMU irq partitions

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     7443813f107a344139b3c7d04161bd7bddea7eda
Gitweb:        https://git.kernel.org/tip/7443813f107a344139b3c7d04161bd7bddea7eda
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:39 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:36 +01:00

irqchip/apple-aic: Drop support for custom PMU irq partitions

Similarly to what has been done for GICv3, drop the irq partitioning support from the AIC driver, effectively merging the two per-cpu interrupts for the PMU.

---
 drivers/irqchip/irq-apple-aic.c | 28 +++++++---------------------
 1 file changed, 7 insertions(+), 21 deletions(-)
drivers/irqchip/irq-apple-aic.c +7 -21
index 0b72451..795b3db 100644
@@ -578,16 +578,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
 	}
 
 	if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
-			(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
-		int irq;
-		if (cpumask_test_cpu(smp_processor_id(),
-				     &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
-			irq = AIC_CPU_PMU_P;
-		else
-			irq = AIC_CPU_PMU_E;
+			(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT))
 		generic_handle_domain_irq(aic_irqc->hw_domain,
-					  AIC_FIQ_HWIRQ(irq));
-	}
+					  AIC_FIQ_HWIRQ(AIC_CPU_PMU_P));
 
 	if (static_branch_likely(&use_fast_ipi) &&
 	    (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) &&
@@ -632,18 +625,7 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
 				    handle_fasteoi_irq, NULL, NULL);
 		irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
 	} else {
-		int fiq = FIELD_GET(AIC_EVENT_NUM, hw);
-
-		switch (fiq) {
-		case AIC_CPU_PMU_P:
-		case AIC_CPU_PMU_E:
-			irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
-			break;
-		default:
-			irq_set_percpu_devid(irq);
-			break;
-		}
-
+		irq_set_percpu_devid(irq);
 		irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
 				    handle_percpu_devid_irq, NULL, NULL);
 	}
@@ -732,6 +714,10 @@ static int aic_irq_domain_translate(struct irq_domain *id,
 				break;
 			}
 		}
+
+		/* Merge the two PMUs on a single interrupt */
+		if (*hwirq == AIC_CPU_PMU_E)
+			*hwirq = AIC_CPU_PMU_P;
 		break;
 	default:
 		return -EINVAL;
author maintainer
#64 lore raw

PATCH v4 23/26 irqchip: Kill irq-partition-percpu

In reply to Marc Zyngier

This code is now completely unused, and nobody will ever miss it.

---
 drivers/irqchip/Kconfig                      |   3 -
 drivers/irqchip/Makefile                     |   1 -
 drivers/irqchip/irq-partition-percpu.c       | 241 -------------------
 include/linux/irqchip/irq-partition-percpu.h |  53 ----
 4 files changed, 298 deletions(-)
 delete mode 100644 drivers/irqchip/irq-partition-percpu.c
 delete mode 100644 include/linux/irqchip/irq-partition-percpu.h
drivers/irqchip/Kconfig +0 -3
index 648b3618fc784..5dddb4c9442ad 100644
@@ -450,9 +450,6 @@ config LS_SCFG_MSI
 	depends on PCI_MSI
 	select IRQ_MSI_LIB
 
-config PARTITION_PERCPU
-	bool
-
 config STM32MP_EXTI
 	tristate "STM32MP extended interrupts and event controller"
 	depends on (ARCH_STM32 && !ARM_SINGLE_ARMV7M) || COMPILE_TEST
drivers/irqchip/Makefile +0 -1
index 3de083f5484cc..6a229443efe08 100644
@@ -36,7 +36,6 @@ obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_ITS_PARENT)	+= irq-gic-its-msi-parent.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v4.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
-obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
 obj-$(CONFIG_ARM_GIC_V5)		+= irq-gic-v5.o irq-gic-v5-irs.o irq-gic-v5-its.o \
 					   irq-gic-v5-iwb.o
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
drivers/irqchip/irq-partition-percpu.c deleted +0 -241

241 lines not on this page · raw message

include/linux/irqchip/irq-partition-percpu.h deleted +0 -53

53 lines not on this page · raw message

Signature · 1 line
2.47.3
merge bot Applied
#65 lore raw

[tip: irq/core] irqchip: Kill irq-partition-percpu

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     c620438ef2ac80b09269a9ae3c0b4fe5add19bfe
Gitweb:        https://git.kernel.org/tip/c620438ef2ac80b09269a9ae3c0b4fe5add19bfe
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:40 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:36 +01:00

irqchip: Kill irq-partition-percpu

This code is now completely unused, and nobody will ever miss it.

---
 drivers/irqchip/Kconfig                      |   3 +-
 drivers/irqchip/Makefile                     |   1 +-
 drivers/irqchip/irq-partition-percpu.c       | 241 +------------------
 include/linux/irqchip/irq-partition-percpu.h |  53 +----
 4 files changed, 298 deletions(-)
 delete mode 100644 drivers/irqchip/irq-partition-percpu.c
 delete mode 100644 include/linux/irqchip/irq-partition-percpu.h
drivers/irqchip/Kconfig +0 -3
index 648b361..5dddb4c 100644
@@ -450,9 +450,6 @@ config LS_SCFG_MSI
 	depends on PCI_MSI
 	select IRQ_MSI_LIB
 
-config PARTITION_PERCPU
-	bool
-
 config STM32MP_EXTI
 	tristate "STM32MP extended interrupts and event controller"
 	depends on (ARCH_STM32 && !ARM_SINGLE_ARMV7M) || COMPILE_TEST
drivers/irqchip/Makefile +0 -1
index 3de083f..6a22944 100644
@@ -36,7 +36,6 @@ obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_ITS_PARENT)	+= irq-gic-its-msi-parent.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v4.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
-obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
 obj-$(CONFIG_ARM_GIC_V5)		+= irq-gic-v5.o irq-gic-v5-irs.o irq-gic-v5-its.o \
 					   irq-gic-v5-iwb.o
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
drivers/irqchip/irq-partition-percpu.c deleted +0 -241

241 lines not on this page · raw message

include/linux/irqchip/irq-partition-percpu.h deleted +0 -53

53 lines not on this page · raw message

author maintainer
#66 lore raw

PATCH v4 24/26 genirq: Kill irq_{g,s}et_percpu_devid_partition()

In reply to Marc Zyngier

These two helpers do not have any user anymore, and can be removed, together with the affinity field kept in the irqdesc structure.

---
 include/linux/irq.h     |  4 ----
 include/linux/irqdesc.h |  1 -
 kernel/irq/irqdesc.c    | 24 +-----------------------
 3 files changed, 1 insertion(+), 28 deletions(-)
include/linux/irq.h +0 -4
index b728c18f6ded7..4a9f1d7b08c39 100644
@@ -718,10 +718,6 @@ static inline void irq_set_chip_and_handler(unsigned int irq,
 }
 
 extern int irq_set_percpu_devid(unsigned int irq);
-extern int irq_set_percpu_devid_partition(unsigned int irq,
-					  const struct cpumask *affinity);
-extern int irq_get_percpu_devid_partition(unsigned int irq,
-					  struct cpumask *affinity);
 
 extern void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
include/linux/irqdesc.h +0 -1
index fd091c35d5721..37e0b5b5600a4 100644
@@ -82,7 +82,6 @@ struct irq_desc {
 	int			threads_handled_last;
 	raw_spinlock_t		lock;
 	struct cpumask		*percpu_enabled;
-	const struct cpumask	*percpu_affinity;
 #ifdef CONFIG_SMP
 	const struct cpumask	*affinity_hint;
 	struct irq_affinity_notify *affinity_notify;
kernel/irq/irqdesc.c +1 -23
index db714d3014b5f..6acf268f005bc 100644
@@ -879,8 +879,7 @@ void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
 		chip_bus_sync_unlock(desc);
 }
 
-int irq_set_percpu_devid_partition(unsigned int irq,
-				   const struct cpumask *affinity)
+int irq_set_percpu_devid(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
@@ -892,31 +891,10 @@ int irq_set_percpu_devid_partition(unsigned int irq,
 	if (!desc->percpu_enabled)
 		return -ENOMEM;
 
-	desc->percpu_affinity = affinity ? : cpu_possible_mask;
-
 	irq_set_percpu_devid_flags(irq);
 	return 0;
 }
 
-int irq_set_percpu_devid(unsigned int irq)
-{
-	return irq_set_percpu_devid_partition(irq, NULL);
-}
-
-int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	if (!desc || !desc->percpu_enabled)
-		return -EINVAL;
-
-	if (affinity)
-		cpumask_copy(affinity, desc->percpu_affinity);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(irq_get_percpu_devid_partition);
-
 void kstat_incr_irq_this_cpu(unsigned int irq)
 {
 	kstat_incr_irqs_this_cpu(irq_to_desc(irq));
Signature · 1 line
2.47.3
merge bot Applied
#67 lore raw

[tip: irq/core] genirq: Kill irq_{g,s}et_percpu_devid_partition()

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     ee2d50a9f524ae829d1a8ec296d7a0170e7b8ade
Gitweb:        https://git.kernel.org/tip/ee2d50a9f524ae829d1a8ec296d7a0170e7b8ade
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:41 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:37 +01:00

genirq: Kill irq_{g,s}et_percpu_devid_partition()

These two helpers do not have any user anymore, and can be removed, together with the affinity field kept in the irqdesc structure.

---
 include/linux/irq.h     |  4 ----
 include/linux/irqdesc.h |  1 -
 kernel/irq/irqdesc.c    | 24 +-----------------------
 3 files changed, 1 insertion(+), 28 deletions(-)
include/linux/irq.h +0 -4
index b728c18..4a9f1d7 100644
@@ -718,10 +718,6 @@ static inline void irq_set_chip_and_handler(unsigned int irq,
 }
 
 extern int irq_set_percpu_devid(unsigned int irq);
-extern int irq_set_percpu_devid_partition(unsigned int irq,
-					  const struct cpumask *affinity);
-extern int irq_get_percpu_devid_partition(unsigned int irq,
-					  struct cpumask *affinity);
 
 extern void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
include/linux/irqdesc.h +0 -1
index fd091c3..37e0b5b 100644
@@ -82,7 +82,6 @@ struct irq_desc {
 	int			threads_handled_last;
 	raw_spinlock_t		lock;
 	struct cpumask		*percpu_enabled;
-	const struct cpumask	*percpu_affinity;
 #ifdef CONFIG_SMP
 	const struct cpumask	*affinity_hint;
 	struct irq_affinity_notify *affinity_notify;
kernel/irq/irqdesc.c +1 -23
index db714d3..6acf268 100644
@@ -879,8 +879,7 @@ void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
 		chip_bus_sync_unlock(desc);
 }
 
-int irq_set_percpu_devid_partition(unsigned int irq,
-				   const struct cpumask *affinity)
+int irq_set_percpu_devid(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
@@ -892,31 +891,10 @@ int irq_set_percpu_devid_partition(unsigned int irq,
 	if (!desc->percpu_enabled)
 		return -ENOMEM;
 
-	desc->percpu_affinity = affinity ? : cpu_possible_mask;
-
 	irq_set_percpu_devid_flags(irq);
 	return 0;
 }
 
-int irq_set_percpu_devid(unsigned int irq)
-{
-	return irq_set_percpu_devid_partition(irq, NULL);
-}
-
-int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	if (!desc || !desc->percpu_enabled)
-		return -EINVAL;
-
-	if (affinity)
-		cpumask_copy(affinity, desc->percpu_affinity);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(irq_get_percpu_devid_partition);
-
 void kstat_incr_irq_this_cpu(unsigned int irq)
 {
 	kstat_incr_irqs_this_cpu(irq_to_desc(irq));
author maintainer
#68 lore raw

PATCH v4 25/26 irqdomain: Kill of_node_to_fwnode() helper

In reply to Marc Zyngier

There is no in-tree users of this helper since b13b41cc3dc18 ("misc:
ti_fpc202: Switch to of_fwnode_handle()"), and is replaced with of_fwnode_handle().

Get rid of it.

---
 include/linux/irqdomain.h | 6 ------
 1 file changed, 6 deletions(-)
include/linux/irqdomain.h +0 -6
index 9d6a5e99394fa..5907baf6099d9 100644
@@ -730,12 +730,6 @@ static inline void msi_device_domain_free_wired(struct irq_domain *domain, unsig
 }
 #endif
 
-/* Deprecated functions. Will be removed in the merge window */
-static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
-{
-	return node ? &node->fwnode : NULL;
-}
-
 static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
 						     const struct irq_domain_ops *ops,
 						     void *host_data)
Signature · 1 line
2.47.3
merge bot Applied
#69 lore raw

[tip: irq/core] irqdomain: Kill of_node_to_fwnode() helper

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     ebac4649fcadc6047030810326875c6e612c7b2f
Gitweb:        https://git.kernel.org/tip/ebac4649fcadc6047030810326875c6e612c7b2f
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:42 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:37 +01:00

irqdomain: Kill of_node_to_fwnode() helper

There is no in-tree users of this helper since b13b41cc3dc18 ("misc:
ti_fpc202: Switch to of_fwnode_handle()"), and is replaced with of_fwnode_handle().

Get rid of it.

---
 include/linux/irqdomain.h | 6 ------
 1 file changed, 6 deletions(-)
include/linux/irqdomain.h +0 -6
index 9d6a5e9..5907baf 100644
@@ -730,12 +730,6 @@ static inline void msi_device_domain_free_wired(struct irq_domain *domain, unsig
 }
 #endif
 
-/* Deprecated functions. Will be removed in the merge window */
-static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
-{
-	return node ? &node->fwnode : NULL;
-}
-
 static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
 						     const struct irq_domain_ops *ops,
 						     void *host_data)
Reviewed-by on v4 25/26
#70 lore raw

Re: [PATCH v4 25/26] irqdomain: Kill of_node_to_fwnode() helper

In reply to Marc Zyngier
Quoted 9 lines · On Mon, 20 Oct 2025 13:29:42 +0100 Marc Zyngier <[email protected]> wrote:

There is no in-tree users of this helper since b13b41cc3dc18 ("misc:
ti_fpc202: Switch to of_fwnode_handle()"), and is replaced with of_fwnode_handle().

Get rid of it.

I didn't bother checking all the other removal patches but didn't see anything wrong with them! Ripping code out is (usually) uncontroversial.

Quoted 21 lines
---
 include/linux/irqdomain.h | 6 ------
 1 file changed, 6 deletions(-)
include/linux/irqdomain.h +0 -6
index 9d6a5e99394fa..5907baf6099d9 100644
@@ -730,12 +730,6 @@ static inline void msi_device_domain_free_wired(struct irq_domain *domain, unsig
 }
 #endif
 
-/* Deprecated functions. Will be removed in the merge window */
-static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
-{
-	return node ? &node->fwnode : NULL;
-}
-
 static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
 						     const struct irq_domain_ops *ops,
 						     void *host_data)
author maintainer
#71 lore raw

PATCH v4 26/26 perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer

In reply to Marc Zyngier

Having removed the use of the cpu_armpmu per-CPU variable from the interrupt handling, the only user left is the BRBE scheduler hook.

It is easy to drop the use of this variable by following the pointer to the generic PMU structure, and get the arm_pmu structure from there.

Perform the conversion and kill cpu_armpmu altogether.

---
 drivers/perf/arm_pmu.c       | 5 -----
 drivers/perf/arm_pmuv3.c     | 2 +-
 include/linux/perf/arm_pmu.h | 2 --
 3 files changed, 1 insertion(+), 8 deletions(-)
drivers/perf/arm_pmu.c +0 -5
index 959ceb3d1f556..f7abd13339630 100644
@@ -104,7 +104,6 @@ static const struct pmu_irq_ops percpu_pmunmi_ops = {
 	.free_pmuirq = armpmu_free_percpu_pmunmi
 };
 
-DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu);
 static DEFINE_PER_CPU(int, cpu_irq);
 static DEFINE_PER_CPU(const struct pmu_irq_ops *, cpu_irq_ops);
 
@@ -725,8 +724,6 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node)
 	if (pmu->reset)
 		pmu->reset(pmu);
 
-	per_cpu(cpu_armpmu, cpu) = pmu;
-
 	irq = armpmu_get_cpu_irq(pmu, cpu);
 	if (irq)
 		per_cpu(cpu_irq_ops, cpu)->enable_pmuirq(irq);
@@ -746,8 +743,6 @@ static int arm_perf_teardown_cpu(unsigned int cpu, struct hlist_node *node)
 	if (irq)
 		per_cpu(cpu_irq_ops, cpu)->disable_pmuirq(irq);
 
-	per_cpu(cpu_armpmu, cpu) = NULL;
-
 	return 0;
 }
 
drivers/perf/arm_pmuv3.c +1 -1
index 69c5cc8f56067..ca8d706d40221 100644
@@ -1064,7 +1064,7 @@ static int armv8pmu_user_event_idx(struct perf_event *event)
 static void armv8pmu_sched_task(struct perf_event_pmu_context *pmu_ctx,
 				struct task_struct *task, bool sched_in)
 {
-	struct arm_pmu *armpmu = *this_cpu_ptr(&cpu_armpmu);
+	struct arm_pmu *armpmu = to_arm_pmu(pmu_ctx->pmu);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
 
 	if (!hw_events->branch_users)
include/linux/perf/arm_pmu.h +0 -2
index 6690bd77aa4ee..bab26a7d79f4c 100644
@@ -132,8 +132,6 @@ struct arm_pmu {
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
-DECLARE_PER_CPU(struct arm_pmu *, cpu_armpmu);
-
 u64 armpmu_event_update(struct perf_event *event);
 
 int armpmu_event_set_period(struct perf_event *event);
Signature · 1 line
2.47.3
merge bot Applied
#72 lore raw

[tip: irq/core] perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     fa9d2777387346645a40ab37cfb0c37b3ef40cc9
Gitweb:        https://git.kernel.org/tip/fa9d2777387346645a40ab37cfb0c37b3ef40cc9
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Mon, 20 Oct 2025 13:29:43 +01:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Mon, 27 Oct 2025 17:16:37 +01:00

perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer

Having removed the use of the cpu_armpmu per-CPU variable from the interrupt handling, the only user left is the BRBE scheduler hook.

It is easy to drop the use of this variable by following the pointer to the generic PMU structure, and get the arm_pmu structure from there.

Perform the conversion and kill cpu_armpmu altogether.

---
 drivers/perf/arm_pmu.c       | 5 -----
 drivers/perf/arm_pmuv3.c     | 2 +-
 include/linux/perf/arm_pmu.h | 2 --
 3 files changed, 1 insertion(+), 8 deletions(-)
drivers/perf/arm_pmu.c +0 -5
index 959ceb3..f7abd13 100644
@@ -104,7 +104,6 @@ static const struct pmu_irq_ops percpu_pmunmi_ops = {
 	.free_pmuirq = armpmu_free_percpu_pmunmi
 };
 
-DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu);
 static DEFINE_PER_CPU(int, cpu_irq);
 static DEFINE_PER_CPU(const struct pmu_irq_ops *, cpu_irq_ops);
 
@@ -725,8 +724,6 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node)
 	if (pmu->reset)
 		pmu->reset(pmu);
 
-	per_cpu(cpu_armpmu, cpu) = pmu;
-
 	irq = armpmu_get_cpu_irq(pmu, cpu);
 	if (irq)
 		per_cpu(cpu_irq_ops, cpu)->enable_pmuirq(irq);
@@ -746,8 +743,6 @@ static int arm_perf_teardown_cpu(unsigned int cpu, struct hlist_node *node)
 	if (irq)
 		per_cpu(cpu_irq_ops, cpu)->disable_pmuirq(irq);
 
-	per_cpu(cpu_armpmu, cpu) = NULL;
-
 	return 0;
 }
 
drivers/perf/arm_pmuv3.c +1 -1
index 69c5cc8..ca8d706 100644
@@ -1064,7 +1064,7 @@ static int armv8pmu_user_event_idx(struct perf_event *event)
 static void armv8pmu_sched_task(struct perf_event_pmu_context *pmu_ctx,
 				struct task_struct *task, bool sched_in)
 {
-	struct arm_pmu *armpmu = *this_cpu_ptr(&cpu_armpmu);
+	struct arm_pmu *armpmu = to_arm_pmu(pmu_ctx->pmu);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
 
 	if (!hw_events->branch_users)
include/linux/perf/arm_pmu.h +0 -2
index 6690bd7..bab26a7 100644
@@ -132,8 +132,6 @@ struct arm_pmu {
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
-DECLARE_PER_CPU(struct arm_pmu *, cpu_armpmu);
-
 u64 armpmu_event_update(struct perf_event *event);
 
 int armpmu_event_set_period(struct perf_event *event);