Skip to content

Commit 6863c83

Browse files
committed
Merge tag 'irq-core-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq core updates from Thomas Gleixner: "Updates for the interrupt core and treewide cleanups: - Rework of the Per Processor Interrupt (PPI) management on ARM[64] PPI support was built under the assumption that the systems are homogenous so that the same CPU local device types are connected to them. That's unfortunately wishful thinking and created horrible workarounds. This rework provides affinity management for PPIs so that they can be individually configured in the firmware tables and mops up the related drivers all over the place. - Prevent CPUSET/isolation changes to arbitrarily affine interrupt threads to random CPUs, which ignores user or driver settings. - Plug a harmless race in the interrupt affinity proc interface, which allows to see a half updated mask - Adjust the priority of secondary interrupt threads on RT, so that the combination of primary and secondary thread emulates the hardware interrupt plus thread scenario. Having them at the same priority can cause starvation issues in some drivers" * tag 'irq-core-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (33 commits) genirq: Remove cpumask availability check on kthread affinity setting genirq: Fix interrupt threads affinity vs. cpuset isolated partitions genirq: Prevent early spurious wake-ups of interrupt threads genirq: Use raw_spinlock_irq() in irq_set_affinity_notifier() genirq/manage: Reduce priority of forced secondary interrupt handler genirq/proc: Fix race in show_irq_affinity() genirq: Fix percpu_devid irq affinity documentation perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer irqdomain: Kill of_node_to_fwnode() helper genirq: Kill irq_{g,s}et_percpu_devid_partition() irqchip: Kill irq-partition-percpu irqchip/apple-aic: Drop support for custom PMU irq partitions irqchip/gic-v3: Drop support for custom PPI partitions coresight: trbe: Request specific affinities for per CPU interrupts perf: arm_spe_pmu: Request specific affinities for per CPU interrupts perf: arm_pmu: Request specific affinities for per CPU NMIs/interrupts genirq: Add request_percpu_irq_affinity() helper genirq: Allow per-cpu interrupt sharing for non-overlapping affinities genirq: Update request_percpu_nmi() to take an affinity genirq: Add affinity to percpu_devid interrupt requests ...
2 parents 312f5b1 + 3de5e46 commit 6863c83

32 files changed

Lines changed: 478 additions & 687 deletions

arch/arm64/kernel/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ static void ipi_setup_sgi(int ipi)
10941094
irq = ipi_irq_base + ipi;
10951095

10961096
if (ipi_should_be_nmi(ipi)) {
1097-
err = request_percpu_nmi(irq, ipi_handler, "IPI", &irq_stat);
1097+
err = request_percpu_nmi(irq, ipi_handler, "IPI", NULL, &irq_stat);
10981098
WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err);
10991099
} else {
11001100
err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);

drivers/acpi/irq.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,25 @@ int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
300300
}
301301
EXPORT_SYMBOL_GPL(acpi_irq_get);
302302

303+
const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
304+
unsigned int index)
305+
{
306+
struct irq_fwspec_info info;
307+
struct irq_fwspec fwspec;
308+
unsigned long flags;
309+
310+
if (acpi_irq_parse_one(handle, index, &fwspec, &flags))
311+
return NULL;
312+
313+
if (irq_populate_fwspec_info(&fwspec, &info))
314+
return NULL;
315+
316+
if (!(info.flags & IRQ_FWSPEC_INFO_AFFINITY_VALID))
317+
return NULL;
318+
319+
return info.affinity;
320+
}
321+
303322
/**
304323
* acpi_set_irq_model - Setup the GSI irqdomain information
305324
* @model: the value assigned to acpi_irq_model

drivers/base/platform.c

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -150,25 +150,37 @@ devm_platform_ioremap_resource_byname(struct platform_device *pdev,
150150
EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname);
151151
#endif /* CONFIG_HAS_IOMEM */
152152

153+
static const struct cpumask *get_irq_affinity(struct platform_device *dev,
154+
unsigned int num)
155+
{
156+
const struct cpumask *mask = NULL;
157+
#ifndef CONFIG_SPARC
158+
struct fwnode_handle *fwnode = dev_fwnode(&dev->dev);
159+
160+
if (is_of_node(fwnode))
161+
mask = of_irq_get_affinity(to_of_node(fwnode), num);
162+
else if (is_acpi_device_node(fwnode))
163+
mask = acpi_irq_get_affinity(ACPI_HANDLE_FWNODE(fwnode), num);
164+
#endif
165+
166+
return mask ?: cpu_possible_mask;
167+
}
168+
153169
/**
154-
* platform_get_irq_optional - get an optional IRQ for a device
155-
* @dev: platform device
156-
* @num: IRQ number index
170+
* platform_get_irq_affinity - get an optional IRQ and its affinity for a device
171+
* @dev: platform device
172+
* @num: interrupt number index
173+
* @affinity: optional cpumask pointer to get the affinity of a per-cpu interrupt
157174
*
158-
* Gets an IRQ for a platform device. Device drivers should check the return
159-
* value for errors so as to not pass a negative integer value to the
160-
* request_irq() APIs. This is the same as platform_get_irq(), except that it
161-
* does not print an error message if an IRQ can not be obtained.
162-
*
163-
* For example::
164-
*
165-
* int irq = platform_get_irq_optional(pdev, 0);
166-
* if (irq < 0)
167-
* return irq;
175+
* Gets an interupt for a platform device. Device drivers should check the
176+
* return value for errors so as to not pass a negative integer value to
177+
* the request_irq() APIs. Optional affinity information is provided in the
178+
* affinity pointer if available, and NULL otherwise.
168179
*
169-
* Return: non-zero IRQ number on success, negative error number on failure.
180+
* Return: non-zero interrupt number on success, negative error number on failure.
170181
*/
171-
int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
182+
int platform_get_irq_affinity(struct platform_device *dev, unsigned int num,
183+
const struct cpumask **affinity)
172184
{
173185
int ret;
174186
#ifdef CONFIG_SPARC
@@ -236,8 +248,37 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
236248
out:
237249
if (WARN(!ret, "0 is an invalid IRQ number\n"))
238250
return -EINVAL;
251+
252+
if (ret > 0 && affinity)
253+
*affinity = get_irq_affinity(dev, num);
254+
239255
return ret;
240256
}
257+
EXPORT_SYMBOL_GPL(platform_get_irq_affinity);
258+
259+
/**
260+
* platform_get_irq_optional - get an optional interrupt for a device
261+
* @dev: platform device
262+
* @num: interrupt number index
263+
*
264+
* Gets an interrupt for a platform device. Device drivers should check the
265+
* return value for errors so as to not pass a negative integer value to
266+
* the request_irq() APIs. This is the same as platform_get_irq(), except
267+
* that it does not print an error message if an interrupt can not be
268+
* obtained.
269+
*
270+
* For example::
271+
*
272+
* int irq = platform_get_irq_optional(pdev, 0);
273+
* if (irq < 0)
274+
* return irq;
275+
*
276+
* Return: non-zero interrupt number on success, negative error number on failure.
277+
*/
278+
int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
279+
{
280+
return platform_get_irq_affinity(dev, num, NULL);
281+
}
241282
EXPORT_SYMBOL_GPL(platform_get_irq_optional);
242283

243284
/**

drivers/hwtracing/coresight/coresight-trbe.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,9 +1474,10 @@ static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata)
14741474
static int arm_trbe_probe_irq(struct platform_device *pdev,
14751475
struct trbe_drvdata *drvdata)
14761476
{
1477+
const struct cpumask *affinity;
14771478
int ret;
14781479

1479-
drvdata->irq = platform_get_irq(pdev, 0);
1480+
drvdata->irq = platform_get_irq_affinity(pdev, 0, &affinity);
14801481
if (drvdata->irq < 0) {
14811482
pr_err("IRQ not found for the platform device\n");
14821483
return drvdata->irq;
@@ -1487,14 +1488,14 @@ static int arm_trbe_probe_irq(struct platform_device *pdev,
14871488
return -EINVAL;
14881489
}
14891490

1490-
if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus))
1491-
return -EINVAL;
1491+
cpumask_copy(&drvdata->supported_cpus, affinity);
14921492

14931493
drvdata->handle = alloc_percpu(struct perf_output_handle *);
14941494
if (!drvdata->handle)
14951495
return -ENOMEM;
14961496

1497-
ret = request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle);
1497+
ret = request_percpu_irq_affinity(drvdata->irq, arm_trbe_irq_handler, DRVNAME,
1498+
affinity, drvdata->handle);
14981499
if (ret) {
14991500
free_percpu(drvdata->handle);
15001501
return ret;

drivers/irqchip/Kconfig

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ config GIC_NON_BANKED
3636
config ARM_GIC_V3
3737
bool
3838
select IRQ_DOMAIN_HIERARCHY
39-
select PARTITION_PERCPU
4039
select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
4140
select HAVE_ARM_SMCCC_DISCOVERY
4241
select IRQ_MSI_IOMMU
@@ -451,9 +450,6 @@ config LS_SCFG_MSI
451450
depends on PCI_MSI
452451
select IRQ_MSI_LIB
453452

454-
config PARTITION_PERCPU
455-
bool
456-
457453
config STM32MP_EXTI
458454
tristate "STM32MP extended interrupts and event controller"
459455
depends on (ARCH_STM32 && !ARM_SINGLE_ARMV7M) || COMPILE_TEST

drivers/irqchip/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
3636
obj-$(CONFIG_ARM_GIC_ITS_PARENT) += irq-gic-its-msi-parent.o
3737
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o
3838
obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
39-
obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o
4039
obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o irq-gic-v5-its.o \
4140
irq-gic-v5-iwb.o
4241
obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o

drivers/irqchip/irq-apple-aic.c

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -578,16 +578,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
578578
}
579579

580580
if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
581-
(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
582-
int irq;
583-
if (cpumask_test_cpu(smp_processor_id(),
584-
&aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
585-
irq = AIC_CPU_PMU_P;
586-
else
587-
irq = AIC_CPU_PMU_E;
581+
(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT))
588582
generic_handle_domain_irq(aic_irqc->hw_domain,
589-
AIC_FIQ_HWIRQ(irq));
590-
}
583+
AIC_FIQ_HWIRQ(AIC_CPU_PMU_P));
591584

592585
if (static_branch_likely(&use_fast_ipi) &&
593586
(FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) &&
@@ -632,25 +625,41 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
632625
handle_fasteoi_irq, NULL, NULL);
633626
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
634627
} else {
635-
int fiq = FIELD_GET(AIC_EVENT_NUM, hw);
636-
637-
switch (fiq) {
638-
case AIC_CPU_PMU_P:
639-
case AIC_CPU_PMU_E:
640-
irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
641-
break;
642-
default:
643-
irq_set_percpu_devid(irq);
644-
break;
645-
}
646-
628+
irq_set_percpu_devid(irq);
647629
irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
648630
handle_percpu_devid_irq, NULL, NULL);
649631
}
650632

651633
return 0;
652634
}
653635

636+
static int aic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
637+
{
638+
const struct cpumask *mask;
639+
u32 intid;
640+
641+
info->flags = 0;
642+
info->affinity = NULL;
643+
644+
if (fwspec->param[0] != AIC_FIQ)
645+
return 0;
646+
647+
if (fwspec->param_count == 3)
648+
intid = fwspec->param[1];
649+
else
650+
intid = fwspec->param[2];
651+
652+
if (aic_irqc->fiq_aff[intid])
653+
mask = &aic_irqc->fiq_aff[intid]->aff;
654+
else
655+
mask = cpu_possible_mask;
656+
657+
info->affinity = mask;
658+
info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
659+
660+
return 0;
661+
}
662+
654663
static int aic_irq_domain_translate(struct irq_domain *id,
655664
struct irq_fwspec *fwspec,
656665
unsigned long *hwirq,
@@ -705,6 +714,10 @@ static int aic_irq_domain_translate(struct irq_domain *id,
705714
break;
706715
}
707716
}
717+
718+
/* Merge the two PMUs on a single interrupt */
719+
if (*hwirq == AIC_CPU_PMU_E)
720+
*hwirq = AIC_CPU_PMU_P;
708721
break;
709722
default:
710723
return -EINVAL;
@@ -750,9 +763,10 @@ static void aic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
750763
}
751764

752765
static const struct irq_domain_ops aic_irq_domain_ops = {
753-
.translate = aic_irq_domain_translate,
754-
.alloc = aic_irq_domain_alloc,
755-
.free = aic_irq_domain_free,
766+
.translate = aic_irq_domain_translate,
767+
.alloc = aic_irq_domain_alloc,
768+
.free = aic_irq_domain_free,
769+
.get_fwspec_info = aic_irq_get_fwspec_info,
756770
};
757771

758772
/*

0 commit comments

Comments
 (0)