Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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
...

+483 -692
+1 -1
arch/arm64/kernel/smp.c
··· 1094 1094 irq = ipi_irq_base + ipi; 1095 1095 1096 1096 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); 1098 1098 WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err); 1099 1099 } else { 1100 1100 err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);
+19
drivers/acpi/irq.c
··· 300 300 } 301 301 EXPORT_SYMBOL_GPL(acpi_irq_get); 302 302 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 + 303 322 /** 304 323 * acpi_set_irq_model - Setup the GSI irqdomain information 305 324 * @model: the value assigned to acpi_irq_model
+56 -15
drivers/base/platform.c
··· 150 150 EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname); 151 151 #endif /* CONFIG_HAS_IOMEM */ 152 152 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 + 153 169 /** 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 157 174 * 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. 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. 162 179 * 163 - * For example:: 164 - * 165 - * int irq = platform_get_irq_optional(pdev, 0); 166 - * if (irq < 0) 167 - * return irq; 168 - * 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. 170 181 */ 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) 172 184 { 173 185 int ret; 174 186 #ifdef CONFIG_SPARC ··· 248 236 out: 249 237 if (WARN(!ret, "0 is an invalid IRQ number\n")) 250 238 return -EINVAL; 239 + 240 + if (ret > 0 && affinity) 241 + *affinity = get_irq_affinity(dev, num); 242 + 251 243 return ret; 244 + } 245 + EXPORT_SYMBOL_GPL(platform_get_irq_affinity); 246 + 247 + /** 248 + * platform_get_irq_optional - get an optional interrupt for a device 249 + * @dev: platform device 250 + * @num: interrupt number index 251 + * 252 + * Gets an interrupt for a platform device. Device drivers should check the 253 + * return value for errors so as to not pass a negative integer value to 254 + * the request_irq() APIs. This is the same as platform_get_irq(), except 255 + * that it does not print an error message if an interrupt can not be 256 + * obtained. 257 + * 258 + * For example:: 259 + * 260 + * int irq = platform_get_irq_optional(pdev, 0); 261 + * if (irq < 0) 262 + * return irq; 263 + * 264 + * Return: non-zero interrupt number on success, negative error number on failure. 265 + */ 266 + int platform_get_irq_optional(struct platform_device *dev, unsigned int num) 267 + { 268 + return platform_get_irq_affinity(dev, num, NULL); 252 269 } 253 270 EXPORT_SYMBOL_GPL(platform_get_irq_optional); 254 271
+5 -4
drivers/hwtracing/coresight/coresight-trbe.c
··· 1474 1474 static int arm_trbe_probe_irq(struct platform_device *pdev, 1475 1475 struct trbe_drvdata *drvdata) 1476 1476 { 1477 + const struct cpumask *affinity; 1477 1478 int ret; 1478 1479 1479 - drvdata->irq = platform_get_irq(pdev, 0); 1480 + drvdata->irq = platform_get_irq_affinity(pdev, 0, &affinity); 1480 1481 if (drvdata->irq < 0) { 1481 1482 pr_err("IRQ not found for the platform device\n"); 1482 1483 return drvdata->irq; ··· 1488 1487 return -EINVAL; 1489 1488 } 1490 1489 1491 - if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus)) 1492 - return -EINVAL; 1490 + cpumask_copy(&drvdata->supported_cpus, affinity); 1493 1491 1494 1492 drvdata->handle = alloc_percpu(struct perf_output_handle *); 1495 1493 if (!drvdata->handle) 1496 1494 return -ENOMEM; 1497 1495 1498 - ret = request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle); 1496 + ret = request_percpu_irq_affinity(drvdata->irq, arm_trbe_irq_handler, DRVNAME, 1497 + affinity, drvdata->handle); 1499 1498 if (ret) { 1500 1499 free_percpu(drvdata->handle); 1501 1500 return ret;
-4
drivers/irqchip/Kconfig
··· 36 36 config ARM_GIC_V3 37 37 bool 38 38 select IRQ_DOMAIN_HIERARCHY 39 - select PARTITION_PERCPU 40 39 select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 41 40 select HAVE_ARM_SMCCC_DISCOVERY 42 41 select IRQ_MSI_IOMMU ··· 449 450 select IRQ_MSI_IOMMU 450 451 depends on PCI_MSI 451 452 select IRQ_MSI_LIB 452 - 453 - config PARTITION_PERCPU 454 - bool 455 453 456 454 config STM32MP_EXTI 457 455 tristate "STM32MP extended interrupts and event controller"
-1
drivers/irqchip/Makefile
··· 36 36 obj-$(CONFIG_ARM_GIC_ITS_PARENT) += irq-gic-its-msi-parent.o 37 37 obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o 38 38 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 40 39 obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o irq-gic-v5-its.o \ 41 40 irq-gic-v5-iwb.o 42 41 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
+38 -24
drivers/irqchip/irq-apple-aic.c
··· 578 578 } 579 579 580 580 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)) 588 582 generic_handle_domain_irq(aic_irqc->hw_domain, 589 - AIC_FIQ_HWIRQ(irq)); 590 - } 583 + AIC_FIQ_HWIRQ(AIC_CPU_PMU_P)); 591 584 592 585 if (static_branch_likely(&use_fast_ipi) && 593 586 (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) && ··· 625 632 handle_fasteoi_irq, NULL, NULL); 626 633 irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); 627 634 } else { 628 - int fiq = FIELD_GET(AIC_EVENT_NUM, hw); 629 - 630 - switch (fiq) { 631 - case AIC_CPU_PMU_P: 632 - case AIC_CPU_PMU_E: 633 - irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff); 634 - break; 635 - default: 636 - irq_set_percpu_devid(irq); 637 - break; 638 - } 639 - 635 + irq_set_percpu_devid(irq); 640 636 irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data, 641 637 handle_percpu_devid_irq, NULL, NULL); 642 638 } 639 + 640 + return 0; 641 + } 642 + 643 + static int aic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 644 + { 645 + const struct cpumask *mask; 646 + u32 intid; 647 + 648 + info->flags = 0; 649 + info->affinity = NULL; 650 + 651 + if (fwspec->param[0] != AIC_FIQ) 652 + return 0; 653 + 654 + if (fwspec->param_count == 3) 655 + intid = fwspec->param[1]; 656 + else 657 + intid = fwspec->param[2]; 658 + 659 + if (aic_irqc->fiq_aff[intid]) 660 + mask = &aic_irqc->fiq_aff[intid]->aff; 661 + else 662 + mask = cpu_possible_mask; 663 + 664 + info->affinity = mask; 665 + info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID; 643 666 644 667 return 0; 645 668 } ··· 714 705 break; 715 706 } 716 707 } 708 + 709 + /* Merge the two PMUs on a single interrupt */ 710 + if (*hwirq == AIC_CPU_PMU_E) 711 + *hwirq = AIC_CPU_PMU_P; 717 712 break; 718 713 default: 719 714 return -EINVAL; ··· 763 750 } 764 751 765 752 static const struct irq_domain_ops aic_irq_domain_ops = { 766 - .translate = aic_irq_domain_translate, 767 - .alloc = aic_irq_domain_alloc, 768 - .free = aic_irq_domain_free, 753 + .translate = aic_irq_domain_translate, 754 + .alloc = aic_irq_domain_alloc, 755 + .free = aic_irq_domain_free, 756 + .get_fwspec_info = aic_irq_get_fwspec_info, 769 757 }; 770 758 771 759 /*
+60 -174
drivers/irqchip/irq-gic-v3.c
··· 26 26 #include <linux/irqchip/arm-gic-common.h> 27 27 #include <linux/irqchip/arm-gic-v3.h> 28 28 #include <linux/irqchip/arm-gic-v3-prio.h> 29 - #include <linux/irqchip/irq-partition-percpu.h> 30 29 #include <linux/bitfield.h> 31 30 #include <linux/bits.h> 32 31 #include <linux/arm-smccc.h> ··· 44 45 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) 45 46 #define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 2) 46 47 #define FLAGS_WORKAROUND_INSECURE (1ULL << 3) 47 - 48 - #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) 49 48 50 49 static struct cpumask broken_rdists __read_mostly __maybe_unused; 51 50 ··· 65 68 u64 flags; 66 69 bool has_rss; 67 70 unsigned int ppi_nr; 68 - struct partition_desc **ppi_descs; 71 + struct partition_affinity *parts; 72 + unsigned int nr_parts; 73 + }; 74 + 75 + struct partition_affinity { 76 + cpumask_t mask; 77 + struct fwnode_handle *partition_id; 69 78 }; 70 79 71 80 #define T241_CHIPS_MAX 4 ··· 230 227 cpus_have_security_disabled, 231 228 !cpus_have_group0); 232 229 } 233 - 234 - /* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */ 235 - static refcount_t *rdist_nmi_refs; 236 230 237 231 static struct gic_kvm_info gic_v3_kvm_info __initdata; 238 232 static DEFINE_PER_CPU(bool, has_rss); ··· 594 594 writeb_relaxed(prio, base + offset + index); 595 595 } 596 596 597 - static u32 __gic_get_ppi_index(irq_hw_number_t hwirq) 598 - { 599 - switch (__get_intid_range(hwirq)) { 600 - case PPI_RANGE: 601 - return hwirq - 16; 602 - case EPPI_RANGE: 603 - return hwirq - EPPI_BASE_INTID + 16; 604 - default: 605 - unreachable(); 606 - } 607 - } 608 - 609 - static u32 __gic_get_rdist_index(irq_hw_number_t hwirq) 610 - { 611 - switch (__get_intid_range(hwirq)) { 612 - case SGI_RANGE: 613 - case PPI_RANGE: 614 - return hwirq; 615 - case EPPI_RANGE: 616 - return hwirq - EPPI_BASE_INTID + 32; 617 - default: 618 - unreachable(); 619 - } 620 - } 621 - 622 - static u32 gic_get_rdist_index(struct irq_data *d) 623 - { 624 - return __gic_get_rdist_index(d->hwirq); 625 - } 626 - 627 597 static int gic_irq_nmi_setup(struct irq_data *d) 628 598 { 629 599 struct irq_desc *desc = irq_to_desc(d->irq); ··· 614 644 return -EINVAL; 615 645 616 646 /* desc lock should already be held */ 617 - if (gic_irq_in_rdist(d)) { 618 - u32 idx = gic_get_rdist_index(d); 619 - 620 - /* 621 - * Setting up a percpu interrupt as NMI, only switch handler 622 - * for first NMI 623 - */ 624 - if (!refcount_inc_not_zero(&rdist_nmi_refs[idx])) { 625 - refcount_set(&rdist_nmi_refs[idx], 1); 626 - desc->handle_irq = handle_percpu_devid_fasteoi_nmi; 627 - } 628 - } else { 647 + if (!gic_irq_in_rdist(d)) 629 648 desc->handle_irq = handle_fasteoi_nmi; 630 - } 631 649 632 650 gic_irq_set_prio(d, dist_prio_nmi); 633 651 ··· 642 684 return; 643 685 644 686 /* desc lock should already be held */ 645 - if (gic_irq_in_rdist(d)) { 646 - u32 idx = gic_get_rdist_index(d); 647 - 648 - /* Tearing down NMI, only switch handler for last NMI */ 649 - if (refcount_dec_and_test(&rdist_nmi_refs[idx])) 650 - desc->handle_irq = handle_percpu_devid_irq; 651 - } else { 687 + if (!gic_irq_in_rdist(d)) 652 688 desc->handle_irq = handle_fasteoi_irq; 653 - } 654 689 655 690 gic_irq_set_prio(d, dist_prio_irq); 656 691 } ··· 1617 1666 case GIC_IRQ_TYPE_LPI: /* LPI */ 1618 1667 *hwirq = fwspec->param[1]; 1619 1668 break; 1620 - case GIC_IRQ_TYPE_PARTITION: 1621 - *hwirq = fwspec->param[1]; 1622 - if (fwspec->param[1] >= 16) 1623 - *hwirq += EPPI_BASE_INTID - 16; 1624 - else 1625 - *hwirq += 16; 1626 - break; 1627 1669 default: 1628 1670 return -EINVAL; 1629 1671 } ··· 1625 1681 1626 1682 /* 1627 1683 * Make it clear that broken DTs are... broken. 1628 - * Partitioned PPIs are an unfortunate exception. 1629 1684 */ 1630 - WARN_ON(*type == IRQ_TYPE_NONE && 1631 - fwspec->param[0] != GIC_IRQ_TYPE_PARTITION); 1685 + WARN_ON(*type == IRQ_TYPE_NONE); 1632 1686 return 0; 1633 1687 } 1634 1688 ··· 1683 1741 } 1684 1742 } 1685 1743 1686 - static bool fwspec_is_partitioned_ppi(struct irq_fwspec *fwspec, 1687 - irq_hw_number_t hwirq) 1688 - { 1689 - enum gic_intid_range range; 1690 - 1691 - if (!gic_data.ppi_descs) 1692 - return false; 1693 - 1694 - if (!is_of_node(fwspec->fwnode)) 1695 - return false; 1696 - 1697 - if (fwspec->param_count < 4 || !fwspec->param[3]) 1698 - return false; 1699 - 1700 - range = __get_intid_range(hwirq); 1701 - if (range != PPI_RANGE && range != EPPI_RANGE) 1702 - return false; 1703 - 1704 - return true; 1705 - } 1706 - 1707 1744 static int gic_irq_domain_select(struct irq_domain *d, 1708 1745 struct irq_fwspec *fwspec, 1709 1746 enum irq_domain_bus_token bus_token) 1710 1747 { 1711 - unsigned int type, ppi_idx; 1712 1748 irq_hw_number_t hwirq; 1749 + unsigned int type; 1713 1750 int ret; 1714 1751 1715 1752 /* Not for us */ ··· 1707 1786 if (WARN_ON_ONCE(ret)) 1708 1787 return 0; 1709 1788 1710 - if (!fwspec_is_partitioned_ppi(fwspec, hwirq)) 1711 - return d == gic_data.domain; 1789 + return d == gic_data.domain; 1790 + } 1712 1791 1713 - /* 1714 - * If this is a PPI and we have a 4th (non-null) parameter, 1715 - * then we need to match the partition domain. 1716 - */ 1717 - ppi_idx = __gic_get_ppi_index(hwirq); 1718 - return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]); 1792 + static int gic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 1793 + { 1794 + const struct cpumask *mask = NULL; 1795 + 1796 + info->flags = 0; 1797 + info->affinity = NULL; 1798 + 1799 + /* ACPI is not capable of describing PPI affinity -- yet */ 1800 + if (!is_of_node(fwspec->fwnode)) 1801 + return 0; 1802 + 1803 + /* If the specifier provides an affinity, use it */ 1804 + if (fwspec->param_count == 4 && fwspec->param[3]) { 1805 + struct fwnode_handle *fw; 1806 + 1807 + switch (fwspec->param[0]) { 1808 + case 1: /* PPI */ 1809 + case 3: /* EPPI */ 1810 + break; 1811 + default: 1812 + return 0; 1813 + } 1814 + 1815 + fw = of_fwnode_handle(of_find_node_by_phandle(fwspec->param[3])); 1816 + if (!fw) 1817 + return -ENOENT; 1818 + 1819 + for (int i = 0; i < gic_data.nr_parts; i++) { 1820 + if (gic_data.parts[i].partition_id == fw) { 1821 + mask = &gic_data.parts[i].mask; 1822 + break; 1823 + } 1824 + } 1825 + 1826 + if (!mask) 1827 + return -ENOENT; 1828 + } else { 1829 + mask = cpu_possible_mask; 1830 + } 1831 + 1832 + info->affinity = mask; 1833 + info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID; 1834 + 1835 + return 0; 1719 1836 } 1720 1837 1721 1838 static const struct irq_domain_ops gic_irq_domain_ops = { ··· 1761 1802 .alloc = gic_irq_domain_alloc, 1762 1803 .free = gic_irq_domain_free, 1763 1804 .select = gic_irq_domain_select, 1764 - }; 1765 - 1766 - static int partition_domain_translate(struct irq_domain *d, 1767 - struct irq_fwspec *fwspec, 1768 - unsigned long *hwirq, 1769 - unsigned int *type) 1770 - { 1771 - unsigned long ppi_intid; 1772 - struct device_node *np; 1773 - unsigned int ppi_idx; 1774 - int ret; 1775 - 1776 - if (!gic_data.ppi_descs) 1777 - return -ENOMEM; 1778 - 1779 - np = of_find_node_by_phandle(fwspec->param[3]); 1780 - if (WARN_ON(!np)) 1781 - return -EINVAL; 1782 - 1783 - ret = gic_irq_domain_translate(d, fwspec, &ppi_intid, type); 1784 - if (WARN_ON_ONCE(ret)) 1785 - return 0; 1786 - 1787 - ppi_idx = __gic_get_ppi_index(ppi_intid); 1788 - ret = partition_translate_id(gic_data.ppi_descs[ppi_idx], 1789 - of_fwnode_handle(np)); 1790 - if (ret < 0) 1791 - return ret; 1792 - 1793 - *hwirq = ret; 1794 - *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; 1795 - 1796 - return 0; 1797 - } 1798 - 1799 - static const struct irq_domain_ops partition_domain_ops = { 1800 - .translate = partition_domain_translate, 1801 - .select = gic_irq_domain_select, 1805 + .get_fwspec_info = gic_irq_get_fwspec_info, 1802 1806 }; 1803 1807 1804 1808 static bool gic_enable_quirk_msm8996(void *data) ··· 1952 2030 1953 2031 static void gic_enable_nmi_support(void) 1954 2032 { 1955 - int i; 1956 - 1957 2033 if (!gic_prio_masking_enabled() || nmi_support_forbidden) 1958 2034 return; 1959 - 1960 - rdist_nmi_refs = kcalloc(gic_data.ppi_nr + SGI_NR, 1961 - sizeof(*rdist_nmi_refs), GFP_KERNEL); 1962 - if (!rdist_nmi_refs) 1963 - return; 1964 - 1965 - for (i = 0; i < gic_data.ppi_nr + SGI_NR; i++) 1966 - refcount_set(&rdist_nmi_refs[i], 0); 1967 2035 1968 2036 pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n", 1969 2037 gic_has_relaxed_pmr_sync() ? "relaxed" : "forced"); ··· 2086 2174 if (!parts_node) 2087 2175 return; 2088 2176 2089 - gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL); 2090 - if (!gic_data.ppi_descs) 2091 - goto out_put_node; 2092 - 2093 2177 nr_parts = of_get_child_count(parts_node); 2094 - 2095 2178 if (!nr_parts) 2096 2179 goto out_put_node; 2097 2180 ··· 2139 2232 part_idx++; 2140 2233 } 2141 2234 2142 - for (i = 0; i < gic_data.ppi_nr; i++) { 2143 - unsigned int irq; 2144 - struct partition_desc *desc; 2145 - struct irq_fwspec ppi_fwspec = { 2146 - .fwnode = gic_data.fwnode, 2147 - .param_count = 3, 2148 - .param = { 2149 - [0] = GIC_IRQ_TYPE_PARTITION, 2150 - [1] = i, 2151 - [2] = IRQ_TYPE_NONE, 2152 - }, 2153 - }; 2154 - 2155 - irq = irq_create_fwspec_mapping(&ppi_fwspec); 2156 - if (WARN_ON(!irq)) 2157 - continue; 2158 - desc = partition_create_desc(gic_data.fwnode, parts, nr_parts, 2159 - irq, &partition_domain_ops); 2160 - if (WARN_ON(!desc)) 2161 - continue; 2162 - 2163 - gic_data.ppi_descs[i] = desc; 2164 - } 2235 + gic_data.parts = parts; 2236 + gic_data.nr_parts = nr_parts; 2165 2237 2166 2238 out_put_node: 2167 2239 of_node_put(parts_node);
-241
drivers/irqchip/irq-partition-percpu.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Copyright (C) 2016 ARM Limited, All Rights Reserved. 4 - * Author: Marc Zyngier <marc.zyngier@arm.com> 5 - */ 6 - 7 - #include <linux/bitops.h> 8 - #include <linux/interrupt.h> 9 - #include <linux/irqchip.h> 10 - #include <linux/irqchip/chained_irq.h> 11 - #include <linux/irqchip/irq-partition-percpu.h> 12 - #include <linux/irqdomain.h> 13 - #include <linux/seq_file.h> 14 - #include <linux/slab.h> 15 - 16 - struct partition_desc { 17 - int nr_parts; 18 - struct partition_affinity *parts; 19 - struct irq_domain *domain; 20 - struct irq_desc *chained_desc; 21 - unsigned long *bitmap; 22 - struct irq_domain_ops ops; 23 - }; 24 - 25 - static bool partition_check_cpu(struct partition_desc *part, 26 - unsigned int cpu, unsigned int hwirq) 27 - { 28 - return cpumask_test_cpu(cpu, &part->parts[hwirq].mask); 29 - } 30 - 31 - static void partition_irq_mask(struct irq_data *d) 32 - { 33 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 34 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 35 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 36 - 37 - if (partition_check_cpu(part, smp_processor_id(), d->hwirq) && 38 - chip->irq_mask) 39 - chip->irq_mask(data); 40 - } 41 - 42 - static void partition_irq_unmask(struct irq_data *d) 43 - { 44 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 45 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 46 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 47 - 48 - if (partition_check_cpu(part, smp_processor_id(), d->hwirq) && 49 - chip->irq_unmask) 50 - chip->irq_unmask(data); 51 - } 52 - 53 - static int partition_irq_set_irqchip_state(struct irq_data *d, 54 - enum irqchip_irq_state which, 55 - bool val) 56 - { 57 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 58 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 59 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 60 - 61 - if (partition_check_cpu(part, smp_processor_id(), d->hwirq) && 62 - chip->irq_set_irqchip_state) 63 - return chip->irq_set_irqchip_state(data, which, val); 64 - 65 - return -EINVAL; 66 - } 67 - 68 - static int partition_irq_get_irqchip_state(struct irq_data *d, 69 - enum irqchip_irq_state which, 70 - bool *val) 71 - { 72 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 73 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 74 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 75 - 76 - if (partition_check_cpu(part, smp_processor_id(), d->hwirq) && 77 - chip->irq_get_irqchip_state) 78 - return chip->irq_get_irqchip_state(data, which, val); 79 - 80 - return -EINVAL; 81 - } 82 - 83 - static int partition_irq_set_type(struct irq_data *d, unsigned int type) 84 - { 85 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 86 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 87 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 88 - 89 - if (chip->irq_set_type) 90 - return chip->irq_set_type(data, type); 91 - 92 - return -EINVAL; 93 - } 94 - 95 - static void partition_irq_print_chip(struct irq_data *d, struct seq_file *p) 96 - { 97 - struct partition_desc *part = irq_data_get_irq_chip_data(d); 98 - struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); 99 - struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); 100 - 101 - seq_printf(p, "%5s-%lu", chip->name, data->hwirq); 102 - } 103 - 104 - static struct irq_chip partition_irq_chip = { 105 - .irq_mask = partition_irq_mask, 106 - .irq_unmask = partition_irq_unmask, 107 - .irq_set_type = partition_irq_set_type, 108 - .irq_get_irqchip_state = partition_irq_get_irqchip_state, 109 - .irq_set_irqchip_state = partition_irq_set_irqchip_state, 110 - .irq_print_chip = partition_irq_print_chip, 111 - }; 112 - 113 - static void partition_handle_irq(struct irq_desc *desc) 114 - { 115 - struct partition_desc *part = irq_desc_get_handler_data(desc); 116 - struct irq_chip *chip = irq_desc_get_chip(desc); 117 - int cpu = smp_processor_id(); 118 - int hwirq; 119 - 120 - chained_irq_enter(chip, desc); 121 - 122 - for_each_set_bit(hwirq, part->bitmap, part->nr_parts) { 123 - if (partition_check_cpu(part, cpu, hwirq)) 124 - break; 125 - } 126 - 127 - if (unlikely(hwirq == part->nr_parts)) 128 - handle_bad_irq(desc); 129 - else 130 - generic_handle_domain_irq(part->domain, hwirq); 131 - 132 - chained_irq_exit(chip, desc); 133 - } 134 - 135 - static int partition_domain_alloc(struct irq_domain *domain, unsigned int virq, 136 - unsigned int nr_irqs, void *arg) 137 - { 138 - int ret; 139 - irq_hw_number_t hwirq; 140 - unsigned int type; 141 - struct irq_fwspec *fwspec = arg; 142 - struct partition_desc *part; 143 - 144 - BUG_ON(nr_irqs != 1); 145 - ret = domain->ops->translate(domain, fwspec, &hwirq, &type); 146 - if (ret) 147 - return ret; 148 - 149 - part = domain->host_data; 150 - 151 - set_bit(hwirq, part->bitmap); 152 - irq_set_chained_handler_and_data(irq_desc_get_irq(part->chained_desc), 153 - partition_handle_irq, part); 154 - irq_set_percpu_devid_partition(virq, &part->parts[hwirq].mask); 155 - irq_domain_set_info(domain, virq, hwirq, &partition_irq_chip, part, 156 - handle_percpu_devid_irq, NULL, NULL); 157 - irq_set_status_flags(virq, IRQ_NOAUTOEN); 158 - 159 - return 0; 160 - } 161 - 162 - static void partition_domain_free(struct irq_domain *domain, unsigned int virq, 163 - unsigned int nr_irqs) 164 - { 165 - struct irq_data *d; 166 - 167 - BUG_ON(nr_irqs != 1); 168 - 169 - d = irq_domain_get_irq_data(domain, virq); 170 - irq_set_handler(virq, NULL); 171 - irq_domain_reset_irq_data(d); 172 - } 173 - 174 - int partition_translate_id(struct partition_desc *desc, void *partition_id) 175 - { 176 - struct partition_affinity *part = NULL; 177 - int i; 178 - 179 - for (i = 0; i < desc->nr_parts; i++) { 180 - if (desc->parts[i].partition_id == partition_id) { 181 - part = &desc->parts[i]; 182 - break; 183 - } 184 - } 185 - 186 - if (WARN_ON(!part)) { 187 - pr_err("Failed to find partition\n"); 188 - return -EINVAL; 189 - } 190 - 191 - return i; 192 - } 193 - 194 - struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode, 195 - struct partition_affinity *parts, 196 - int nr_parts, 197 - int chained_irq, 198 - const struct irq_domain_ops *ops) 199 - { 200 - struct partition_desc *desc; 201 - struct irq_domain *d; 202 - 203 - BUG_ON(!ops->select || !ops->translate); 204 - 205 - desc = kzalloc(sizeof(*desc), GFP_KERNEL); 206 - if (!desc) 207 - return NULL; 208 - 209 - desc->ops = *ops; 210 - desc->ops.free = partition_domain_free; 211 - desc->ops.alloc = partition_domain_alloc; 212 - 213 - d = irq_domain_create_linear(fwnode, nr_parts, &desc->ops, desc); 214 - if (!d) 215 - goto out; 216 - desc->domain = d; 217 - 218 - desc->bitmap = bitmap_zalloc(nr_parts, GFP_KERNEL); 219 - if (WARN_ON(!desc->bitmap)) 220 - goto out; 221 - 222 - desc->chained_desc = irq_to_desc(chained_irq); 223 - desc->nr_parts = nr_parts; 224 - desc->parts = parts; 225 - 226 - return desc; 227 - out: 228 - if (d) 229 - irq_domain_remove(d); 230 - kfree(desc); 231 - 232 - return NULL; 233 - } 234 - 235 - struct irq_domain *partition_get_domain(struct partition_desc *dsc) 236 - { 237 - if (dsc) 238 - return dsc->domain; 239 - 240 - return NULL; 241 - }
+20
drivers/of/irq.c
··· 479 479 } 480 480 EXPORT_SYMBOL_GPL(of_irq_get); 481 481 482 + const struct cpumask *of_irq_get_affinity(struct device_node *dev, int index) 483 + { 484 + struct of_phandle_args oirq; 485 + struct irq_fwspec_info info; 486 + struct irq_fwspec fwspec; 487 + int rc; 488 + 489 + rc = of_irq_parse_one(dev, index, &oirq); 490 + if (rc) 491 + return NULL; 492 + 493 + of_phandle_args_to_fwspec(oirq.np, oirq.args, oirq.args_count, 494 + &fwspec); 495 + 496 + if (irq_populate_fwspec_info(&fwspec, &info)) 497 + return NULL; 498 + 499 + return info.affinity; 500 + } 501 + 482 502 /** 483 503 * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number 484 504 * @dev: pointer to device tree node
+26 -23
drivers/perf/arm_pmu.c
··· 26 26 27 27 #include <asm/irq_regs.h> 28 28 29 - static int armpmu_count_irq_users(const int irq); 29 + static int armpmu_count_irq_users(const struct cpumask *affinity, 30 + const int irq); 30 31 31 32 struct pmu_irq_ops { 32 33 void (*enable_pmuirq)(unsigned int irq); ··· 65 64 static void armpmu_free_percpu_pmuirq(unsigned int irq, int cpu, 66 65 void __percpu *devid) 67 66 { 68 - if (armpmu_count_irq_users(irq) == 1) 67 + struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu); 68 + 69 + if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1) 69 70 free_percpu_irq(irq, devid); 70 71 } 71 72 ··· 92 89 static void armpmu_free_percpu_pmunmi(unsigned int irq, int cpu, 93 90 void __percpu *devid) 94 91 { 95 - if (armpmu_count_irq_users(irq) == 1) 92 + struct arm_pmu *armpmu = *per_cpu_ptr((void * __percpu *)devid, cpu); 93 + 94 + if (armpmu_count_irq_users(&armpmu->supported_cpus, irq) == 1) 96 95 free_percpu_nmi(irq, devid); 97 96 } 98 97 ··· 104 99 .free_pmuirq = armpmu_free_percpu_pmunmi 105 100 }; 106 101 107 - DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu); 108 102 static DEFINE_PER_CPU(int, cpu_irq); 109 103 static DEFINE_PER_CPU(const struct pmu_irq_ops *, cpu_irq_ops); 110 104 ··· 584 580 .attrs = armpmu_common_attrs, 585 581 }; 586 582 587 - static int armpmu_count_irq_users(const int irq) 583 + static int armpmu_count_irq_users(const struct cpumask *affinity, const int irq) 588 584 { 589 585 int cpu, count = 0; 590 586 591 - for_each_possible_cpu(cpu) { 587 + for_each_cpu(cpu, affinity) { 592 588 if (per_cpu(cpu_irq, cpu) == irq) 593 589 count++; 594 590 } ··· 596 592 return count; 597 593 } 598 594 599 - static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq) 595 + static const struct pmu_irq_ops * 596 + armpmu_find_irq_ops(const struct cpumask *affinity, int irq) 600 597 { 601 598 const struct pmu_irq_ops *ops = NULL; 602 599 int cpu; 603 600 604 - for_each_possible_cpu(cpu) { 601 + for_each_cpu(cpu, affinity) { 605 602 if (per_cpu(cpu_irq, cpu) != irq) 606 603 continue; 607 604 ··· 614 609 return ops; 615 610 } 616 611 617 - void armpmu_free_irq(int irq, int cpu) 612 + void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu) 618 613 { 619 614 if (per_cpu(cpu_irq, cpu) == 0) 620 615 return; 621 616 if (WARN_ON(irq != per_cpu(cpu_irq, cpu))) 622 617 return; 623 618 624 - per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, &cpu_armpmu); 619 + per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, armpmu); 625 620 626 621 per_cpu(cpu_irq, cpu) = 0; 627 622 per_cpu(cpu_irq_ops, cpu) = NULL; 628 623 } 629 624 630 - int armpmu_request_irq(int irq, int cpu) 625 + int armpmu_request_irq(struct arm_pmu * __percpu *pcpu_armpmu, int irq, int cpu) 631 626 { 632 627 int err = 0; 628 + struct arm_pmu **armpmu = per_cpu_ptr(pcpu_armpmu, cpu); 629 + const struct cpumask *affinity = *armpmu ? &(*armpmu)->supported_cpus : 630 + cpu_possible_mask; /* ACPI */ 633 631 const irq_handler_t handler = armpmu_dispatch_irq; 634 632 const struct pmu_irq_ops *irq_ops; 635 633 ··· 654 646 IRQF_NOBALANCING | IRQF_NO_AUTOEN | 655 647 IRQF_NO_THREAD; 656 648 657 - err = request_nmi(irq, handler, irq_flags, "arm-pmu", 658 - per_cpu_ptr(&cpu_armpmu, cpu)); 649 + err = request_nmi(irq, handler, irq_flags, "arm-pmu", armpmu); 659 650 660 651 /* If cannot get an NMI, get a normal interrupt */ 661 652 if (err) { 662 653 err = request_irq(irq, handler, irq_flags, "arm-pmu", 663 - per_cpu_ptr(&cpu_armpmu, cpu)); 654 + armpmu); 664 655 irq_ops = &pmuirq_ops; 665 656 } else { 666 657 has_nmi = true; 667 658 irq_ops = &pmunmi_ops; 668 659 } 669 - } else if (armpmu_count_irq_users(irq) == 0) { 670 - err = request_percpu_nmi(irq, handler, "arm-pmu", &cpu_armpmu); 660 + } else if (armpmu_count_irq_users(affinity, irq) == 0) { 661 + err = request_percpu_nmi(irq, handler, "arm-pmu", affinity, pcpu_armpmu); 671 662 672 663 /* If cannot get an NMI, get a normal interrupt */ 673 664 if (err) { 674 - err = request_percpu_irq(irq, handler, "arm-pmu", 675 - &cpu_armpmu); 665 + err = request_percpu_irq_affinity(irq, handler, "arm-pmu", 666 + affinity, pcpu_armpmu); 676 667 irq_ops = &percpu_pmuirq_ops; 677 668 } else { 678 669 has_nmi = true; ··· 679 672 } 680 673 } else { 681 674 /* Per cpudevid irq was already requested by another CPU */ 682 - irq_ops = armpmu_find_irq_ops(irq); 675 + irq_ops = armpmu_find_irq_ops(affinity, irq); 683 676 684 677 if (WARN_ON(!irq_ops)) 685 678 err = -EINVAL; ··· 724 717 if (pmu->reset) 725 718 pmu->reset(pmu); 726 719 727 - per_cpu(cpu_armpmu, cpu) = pmu; 728 - 729 720 irq = armpmu_get_cpu_irq(pmu, cpu); 730 721 if (irq) 731 722 per_cpu(cpu_irq_ops, cpu)->enable_pmuirq(irq); ··· 742 737 irq = armpmu_get_cpu_irq(pmu, cpu); 743 738 if (irq) 744 739 per_cpu(cpu_irq_ops, cpu)->disable_pmuirq(irq); 745 - 746 - per_cpu(cpu_armpmu, cpu) = NULL; 747 740 748 741 return 0; 749 742 }
+1 -1
drivers/perf/arm_pmu_acpi.c
··· 218 218 * them with their PMUs. 219 219 */ 220 220 per_cpu(pmu_irqs, cpu) = irq; 221 - err = armpmu_request_irq(irq, cpu); 221 + err = armpmu_request_irq(&probed_pmus, irq, cpu); 222 222 if (err) 223 223 goto out_err; 224 224 }
+11 -9
drivers/perf/arm_pmu_platform.c
··· 42 42 return ret; 43 43 } 44 44 45 - static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq) 45 + static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq, 46 + const struct cpumask *affinity) 46 47 { 47 - int cpu, ret; 48 48 struct pmu_hw_events __percpu *hw_events = pmu->hw_events; 49 + int cpu; 49 50 50 - ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus); 51 - if (ret) 52 - return ret; 51 + cpumask_copy(&pmu->supported_cpus, affinity); 53 52 54 53 for_each_cpu(cpu, &pmu->supported_cpus) 55 54 per_cpu(hw_events->irq, cpu) = irq; ··· 114 115 } 115 116 116 117 if (num_irqs == 1) { 117 - int irq = platform_get_irq(pdev, 0); 118 + const struct cpumask *affinity; 119 + int irq; 120 + 121 + irq = platform_get_irq_affinity(pdev, 0, &affinity); 118 122 if ((irq > 0) && irq_is_percpu_devid(irq)) 119 - return pmu_parse_percpu_irq(pmu, irq); 123 + return pmu_parse_percpu_irq(pmu, irq, affinity); 120 124 } 121 125 122 126 if (nr_cpu_ids != 1 && !pmu_has_irq_affinity(dev->of_node)) ··· 165 163 if (!irq) 166 164 continue; 167 165 168 - err = armpmu_request_irq(irq, cpu); 166 + err = armpmu_request_irq(&hw_events->percpu_pmu, irq, cpu); 169 167 if (err) 170 168 break; 171 169 } ··· 181 179 for_each_cpu(cpu, &armpmu->supported_cpus) { 182 180 int irq = per_cpu(hw_events->irq, cpu); 183 181 184 - armpmu_free_irq(irq, cpu); 182 + armpmu_free_irq(&hw_events->percpu_pmu, irq, cpu); 185 183 } 186 184 } 187 185
+1 -1
drivers/perf/arm_pmuv3.c
··· 1064 1064 static void armv8pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, 1065 1065 struct task_struct *task, bool sched_in) 1066 1066 { 1067 - struct arm_pmu *armpmu = *this_cpu_ptr(&cpu_armpmu); 1067 + struct arm_pmu *armpmu = to_arm_pmu(pmu_ctx->pmu); 1068 1068 struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events); 1069 1069 1070 1070 if (!hw_events->branch_users)
+6 -7
drivers/perf/arm_spe_pmu.c
··· 1259 1259 return -ENXIO; 1260 1260 1261 1261 /* Request our PPIs (note that the IRQ is still disabled) */ 1262 - ret = request_percpu_irq(spe_pmu->irq, arm_spe_pmu_irq_handler, DRVNAME, 1263 - spe_pmu->handle); 1262 + ret = request_percpu_irq_affinity(spe_pmu->irq, arm_spe_pmu_irq_handler, 1263 + DRVNAME, mask, spe_pmu->handle); 1264 1264 if (ret) 1265 1265 return ret; 1266 1266 ··· 1287 1287 static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu) 1288 1288 { 1289 1289 struct platform_device *pdev = spe_pmu->pdev; 1290 - int irq = platform_get_irq(pdev, 0); 1290 + const struct cpumask *affinity; 1291 + int irq; 1291 1292 1293 + irq = platform_get_irq_affinity(pdev, 0, &affinity); 1292 1294 if (irq < 0) 1293 1295 return -ENXIO; 1294 1296 ··· 1299 1297 return -EINVAL; 1300 1298 } 1301 1299 1302 - if (irq_get_percpu_devid_partition(irq, &spe_pmu->supported_cpus)) { 1303 - dev_err(&pdev->dev, "failed to get PPI partition (%d)\n", irq); 1304 - return -EINVAL; 1305 - } 1300 + cpumask_copy(&spe_pmu->supported_cpus, affinity); 1306 1301 1307 1302 spe_pmu->irq = irq; 1308 1303 return 0;
+7
include/linux/acpi.h
··· 1509 1509 1510 1510 #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI) 1511 1511 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res); 1512 + const struct cpumask *acpi_irq_get_affinity(acpi_handle handle, 1513 + unsigned int index); 1512 1514 #else 1513 1515 static inline 1514 1516 int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res) 1515 1517 { 1516 1518 return -EINVAL; 1519 + } 1520 + static inline const struct cpumask *acpi_irq_get_affinity(acpi_handle handle, 1521 + unsigned int index) 1522 + { 1523 + return NULL; 1517 1524 } 1518 1525 #endif 1519 1526
+19 -6
include/linux/interrupt.h
··· 109 109 * @name: name of the device 110 110 * @dev_id: cookie to identify the device 111 111 * @percpu_dev_id: cookie to identify the device 112 + * @affinity: CPUs this irqaction is allowed to run on 112 113 * @next: pointer to the next irqaction for shared interrupts 113 114 * @irq: interrupt number 114 115 * @flags: flags (see IRQF_* above) ··· 122 121 */ 123 122 struct irqaction { 124 123 irq_handler_t handler; 125 - void *dev_id; 126 - void __percpu *percpu_dev_id; 124 + union { 125 + void *dev_id; 126 + void __percpu *percpu_dev_id; 127 + }; 128 + const struct cpumask *affinity; 127 129 struct irqaction *next; 128 130 irq_handler_t thread_fn; 129 131 struct task_struct *thread; ··· 183 179 extern int __must_check 184 180 __request_percpu_irq(unsigned int irq, irq_handler_t handler, 185 181 unsigned long flags, const char *devname, 186 - void __percpu *percpu_dev_id); 182 + const cpumask_t *affinity, void __percpu *percpu_dev_id); 187 183 188 184 extern int __must_check 189 185 request_nmi(unsigned int irq, irq_handler_t handler, unsigned long flags, ··· 194 190 const char *devname, void __percpu *percpu_dev_id) 195 191 { 196 192 return __request_percpu_irq(irq, handler, 0, 197 - devname, percpu_dev_id); 193 + devname, NULL, percpu_dev_id); 194 + } 195 + 196 + static inline int __must_check 197 + request_percpu_irq_affinity(unsigned int irq, irq_handler_t handler, 198 + const char *devname, const cpumask_t *affinity, 199 + void __percpu *percpu_dev_id) 200 + { 201 + return __request_percpu_irq(irq, handler, 0, 202 + devname, affinity, percpu_dev_id); 198 203 } 199 204 200 205 extern int __must_check 201 - request_percpu_nmi(unsigned int irq, irq_handler_t handler, 202 - const char *devname, void __percpu *dev); 206 + request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name, 207 + const struct cpumask *affinity, void __percpu *dev_id); 203 208 204 209 extern const void *free_irq(unsigned int, void *); 205 210 extern void free_percpu_irq(unsigned int, void __percpu *);
-5
include/linux/irq.h
··· 655 655 extern void handle_nested_irq(unsigned int irq); 656 656 657 657 extern void handle_fasteoi_nmi(struct irq_desc *desc); 658 - extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc); 659 658 660 659 extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); 661 660 extern int irq_chip_pm_get(struct irq_data *data); ··· 718 719 } 719 720 720 721 extern int irq_set_percpu_devid(unsigned int irq); 721 - extern int irq_set_percpu_devid_partition(unsigned int irq, 722 - const struct cpumask *affinity); 723 - extern int irq_get_percpu_devid_partition(unsigned int irq, 724 - struct cpumask *affinity); 725 722 726 723 extern void 727 724 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
-53
include/linux/irqchip/irq-partition-percpu.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * Copyright (C) 2016 ARM Limited, All Rights Reserved. 4 - * Author: Marc Zyngier <marc.zyngier@arm.com> 5 - */ 6 - 7 - #ifndef __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H 8 - #define __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H 9 - 10 - #include <linux/fwnode.h> 11 - #include <linux/cpumask_types.h> 12 - #include <linux/irqdomain.h> 13 - 14 - struct partition_affinity { 15 - cpumask_t mask; 16 - void *partition_id; 17 - }; 18 - 19 - struct partition_desc; 20 - 21 - #ifdef CONFIG_PARTITION_PERCPU 22 - int partition_translate_id(struct partition_desc *desc, void *partition_id); 23 - struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode, 24 - struct partition_affinity *parts, 25 - int nr_parts, 26 - int chained_irq, 27 - const struct irq_domain_ops *ops); 28 - struct irq_domain *partition_get_domain(struct partition_desc *dsc); 29 - #else 30 - static inline int partition_translate_id(struct partition_desc *desc, 31 - void *partition_id) 32 - { 33 - return -EINVAL; 34 - } 35 - 36 - static inline 37 - struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode, 38 - struct partition_affinity *parts, 39 - int nr_parts, 40 - int chained_irq, 41 - const struct irq_domain_ops *ops) 42 - { 43 - return NULL; 44 - } 45 - 46 - static inline 47 - struct irq_domain *partition_get_domain(struct partition_desc *dsc) 48 - { 49 - return NULL; 50 - } 51 - #endif 52 - 53 - #endif /* __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H */
-1
include/linux/irqdesc.h
··· 82 82 int threads_handled_last; 83 83 raw_spinlock_t lock; 84 84 struct cpumask *percpu_enabled; 85 - const struct cpumask *percpu_affinity; 86 85 #ifdef CONFIG_SMP 87 86 const struct cpumask *affinity_hint; 88 87 struct irq_affinity_notify *affinity_notify;
+27 -6
include/linux/irqdomain.h
··· 44 44 u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS]; 45 45 }; 46 46 47 + /** 48 + * struct irq_fwspec_info - firmware provided IRQ information structure 49 + * 50 + * @flags: Information validity flags 51 + * @affinity: Affinity mask for this interrupt 52 + * 53 + * This structure reports firmware-specific information about an 54 + * interrupt. The only significant information is the affinity of a 55 + * per-CPU interrupt, but this is designed to be extended as required. 56 + */ 57 + struct irq_fwspec_info { 58 + unsigned long flags; 59 + const struct cpumask *affinity; 60 + }; 61 + 62 + #define IRQ_FWSPEC_INFO_AFFINITY_VALID BIT(0) 63 + 47 64 /* Conversion function from of_phandle_args fields to fwspec */ 48 65 void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, 49 66 unsigned int count, struct irq_fwspec *fwspec); ··· 86 69 * @translate: Given @fwspec, decode the hardware irq number (@out_hwirq) and 87 70 * linux irq type value (@out_type). This is a generalised @xlate 88 71 * (over struct irq_fwspec) and is preferred if provided. 72 + * @get_fwspec_info: 73 + * Given @fwspec, report additional firmware-provided information in 74 + * @info. Optional. 89 75 * @debug_show: For domains to show specific data for an interrupt in debugfs. 90 76 * 91 77 * Functions below are provided by the driver and called whenever a new mapping ··· 116 96 void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data); 117 97 int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, 118 98 unsigned long *out_hwirq, unsigned int *out_type); 99 + int (*get_fwspec_info)(struct irq_fwspec *fwspec, struct irq_fwspec_info *info); 119 100 #endif 120 101 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS 121 102 void (*debug_show)(struct seq_file *m, struct irq_domain *d, ··· 623 602 624 603 int irq_domain_disconnect_hierarchy(struct irq_domain *domain, unsigned int virq); 625 604 605 + int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info); 606 + 626 607 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain) 627 608 { 628 609 return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY; ··· 708 685 return false; 709 686 } 710 687 688 + static inline int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 689 + { 690 + return -EINVAL; 691 + } 711 692 #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 712 693 713 694 #ifdef CONFIG_GENERIC_MSI_IRQ ··· 729 702 WARN_ON_ONCE(1); 730 703 } 731 704 #endif 732 - 733 - /* Deprecated functions. Will be removed in the merge window */ 734 - static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node) 735 - { 736 - return node ? &node->fwnode : NULL; 737 - } 738 705 739 706 static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node, 740 707 const struct irq_domain_ops *ops,
+7
include/linux/of_irq.h
··· 43 43 struct of_phandle_args *out_irq); 44 44 extern int of_irq_count(struct device_node *dev); 45 45 extern int of_irq_get(struct device_node *dev, int index); 46 + extern const struct cpumask *of_irq_get_affinity(struct device_node *dev, 47 + int index); 46 48 extern int of_irq_get_byname(struct device_node *dev, const char *name); 47 49 extern int of_irq_to_resource_table(struct device_node *dev, 48 50 struct resource *res, int nr_irqs); ··· 77 75 static inline int of_irq_get_byname(struct device_node *dev, const char *name) 78 76 { 79 77 return 0; 78 + } 79 + static inline const struct cpumask *of_irq_get_affinity(struct device_node *dev, 80 + int index) 81 + { 82 + return NULL; 80 83 } 81 84 static inline int of_irq_to_resource_table(struct device_node *dev, 82 85 struct resource *res, int nr_irqs)
+2 -4
include/linux/perf/arm_pmu.h
··· 132 132 133 133 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) 134 134 135 - DECLARE_PER_CPU(struct arm_pmu *, cpu_armpmu); 136 - 137 135 u64 armpmu_event_update(struct perf_event *event); 138 136 139 137 int armpmu_event_set_period(struct perf_event *event); ··· 188 190 struct arm_pmu *armpmu_alloc(void); 189 191 void armpmu_free(struct arm_pmu *pmu); 190 192 int armpmu_register(struct arm_pmu *pmu); 191 - int armpmu_request_irq(int irq, int cpu); 192 - void armpmu_free_irq(int irq, int cpu); 193 + int armpmu_request_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu); 194 + void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu); 193 195 194 196 #define ARMV8_PMU_PDEV_NAME "armv8-pmu" 195 197
+2
include/linux/platform_device.h
··· 102 102 103 103 extern int platform_get_irq(struct platform_device *, unsigned int); 104 104 extern int platform_get_irq_optional(struct platform_device *, unsigned int); 105 + extern int platform_get_irq_affinity(struct platform_device *, unsigned int, 106 + const struct cpumask **); 105 107 extern int platform_irq_count(struct platform_device *); 106 108 extern int devm_platform_get_irqs_affinity(struct platform_device *dev, 107 109 struct irq_affinity *affd,
+1
include/linux/sched.h
··· 1876 1876 extern int sched_setscheduler_nocheck(struct task_struct *, int, const struct sched_param *); 1877 1877 extern void sched_set_fifo(struct task_struct *p); 1878 1878 extern void sched_set_fifo_low(struct task_struct *p); 1879 + extern void sched_set_fifo_secondary(struct task_struct *p); 1879 1880 extern void sched_set_normal(struct task_struct *p, int nice); 1880 1881 extern int sched_setattr(struct task_struct *, const struct sched_attr *); 1881 1882 extern int sched_setattr_nocheck(struct task_struct *, const struct sched_attr *);
+6 -27
kernel/irq/chip.c
··· 897 897 void handle_percpu_devid_irq(struct irq_desc *desc) 898 898 { 899 899 struct irq_chip *chip = irq_desc_get_chip(desc); 900 - struct irqaction *action = desc->action; 901 900 unsigned int irq = irq_desc_get_irq(desc); 901 + unsigned int cpu = smp_processor_id(); 902 + struct irqaction *action; 902 903 irqreturn_t res; 903 904 904 905 /* ··· 911 910 if (chip->irq_ack) 912 911 chip->irq_ack(&desc->irq_data); 913 912 913 + for (action = desc->action; action; action = action->next) 914 + if (cpumask_test_cpu(cpu, action->affinity)) 915 + break; 916 + 914 917 if (likely(action)) { 915 918 trace_irq_handler_entry(irq, action); 916 919 res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); 917 920 trace_irq_handler_exit(irq, action, res); 918 921 } else { 919 - unsigned int cpu = smp_processor_id(); 920 922 bool enabled = cpumask_test_cpu(cpu, desc->percpu_enabled); 921 923 922 924 if (enabled) ··· 928 924 pr_err_once("Spurious%s percpu IRQ%u on CPU%u\n", 929 925 enabled ? " and unmasked" : "", irq, cpu); 930 926 } 931 - 932 - if (chip->irq_eoi) 933 - chip->irq_eoi(&desc->irq_data); 934 - } 935 - 936 - /** 937 - * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu 938 - * dev ids 939 - * @desc: the interrupt description structure for this irq 940 - * 941 - * Similar to handle_fasteoi_nmi, but handling the dev_id cookie 942 - * as a percpu pointer. 943 - */ 944 - void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc) 945 - { 946 - struct irq_chip *chip = irq_desc_get_chip(desc); 947 - struct irqaction *action = desc->action; 948 - unsigned int irq = irq_desc_get_irq(desc); 949 - irqreturn_t res; 950 - 951 - __kstat_incr_irqs_this_cpu(desc); 952 - 953 - trace_irq_handler_entry(irq, action); 954 - res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); 955 - trace_irq_handler_exit(irq, action, res); 956 927 957 928 if (chip->irq_eoi) 958 929 chip->irq_eoi(&desc->irq_data);
+9 -1
kernel/irq/handle.c
··· 133 133 */ 134 134 atomic_inc(&desc->threads_active); 135 135 136 - wake_up_process(action->thread); 136 + /* 137 + * This might be a premature wakeup before the thread reached the 138 + * thread function and set the IRQTF_READY bit. It's waiting in 139 + * kthread code with state UNINTERRUPTIBLE. Once it reaches the 140 + * thread function it waits with INTERRUPTIBLE. The wakeup is not 141 + * lost in that case because the thread is guaranteed to observe 142 + * the RUN flag before it goes to sleep in wait_for_interrupt(). 143 + */ 144 + wake_up_state(action->thread, TASK_INTERRUPTIBLE); 137 145 } 138 146 139 147 static DEFINE_STATIC_KEY_FALSE(irqhandler_duration_check_enabled);
+1 -23
kernel/irq/irqdesc.c
··· 879 879 chip_bus_sync_unlock(desc); 880 880 } 881 881 882 - int irq_set_percpu_devid_partition(unsigned int irq, 883 - const struct cpumask *affinity) 882 + int irq_set_percpu_devid(unsigned int irq) 884 883 { 885 884 struct irq_desc *desc = irq_to_desc(irq); 886 885 ··· 891 892 if (!desc->percpu_enabled) 892 893 return -ENOMEM; 893 894 894 - desc->percpu_affinity = affinity ? : cpu_possible_mask; 895 - 896 895 irq_set_percpu_devid_flags(irq); 897 896 return 0; 898 897 } 899 - 900 - int irq_set_percpu_devid(unsigned int irq) 901 - { 902 - return irq_set_percpu_devid_partition(irq, NULL); 903 - } 904 - 905 - int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity) 906 - { 907 - struct irq_desc *desc = irq_to_desc(irq); 908 - 909 - if (!desc || !desc->percpu_enabled) 910 - return -EINVAL; 911 - 912 - if (affinity) 913 - cpumask_copy(affinity, desc->percpu_affinity); 914 - 915 - return 0; 916 - } 917 - EXPORT_SYMBOL_GPL(irq_get_percpu_devid_partition); 918 898 919 899 void kstat_incr_irq_this_cpu(unsigned int irq) 920 900 {
+27 -5
kernel/irq/irqdomain.c
··· 867 867 } 868 868 EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec); 869 869 870 - unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) 870 + static struct irq_domain *fwspec_to_domain(struct irq_fwspec *fwspec) 871 871 { 872 872 struct irq_domain *domain; 873 - struct irq_data *irq_data; 874 - irq_hw_number_t hwirq; 875 - unsigned int type = IRQ_TYPE_NONE; 876 - int virq; 877 873 878 874 if (fwspec->fwnode) { 879 875 domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED); ··· 879 883 domain = irq_default_domain; 880 884 } 881 885 886 + return domain; 887 + } 888 + 889 + #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 890 + int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 891 + { 892 + struct irq_domain *domain = fwspec_to_domain(fwspec); 893 + 894 + memset(info, 0, sizeof(*info)); 895 + 896 + if (!domain || !domain->ops->get_fwspec_info) 897 + return 0; 898 + 899 + return domain->ops->get_fwspec_info(fwspec, info); 900 + } 901 + #endif 902 + 903 + unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) 904 + { 905 + unsigned int type = IRQ_TYPE_NONE; 906 + struct irq_domain *domain; 907 + struct irq_data *irq_data; 908 + irq_hw_number_t hwirq; 909 + int virq; 910 + 911 + domain = fwspec_to_domain(fwspec); 882 912 if (!domain) { 883 913 pr_warn("no irq domain found for %s !\n", 884 914 of_node_full_name(to_of_node(fwspec->fwnode)));
+116 -56
kernel/irq/manage.c
··· 547 547 INIT_WORK(&notify->work, irq_affinity_notify); 548 548 } 549 549 550 - scoped_guard(raw_spinlock_irqsave, &desc->lock) { 550 + scoped_guard(raw_spinlock_irq, &desc->lock) { 551 551 old_notify = desc->affinity_notify; 552 552 desc->affinity_notify = notify; 553 553 } ··· 1001 1001 static void irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) 1002 1002 { 1003 1003 cpumask_var_t mask; 1004 - bool valid = false; 1005 1004 1006 1005 if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags)) 1007 1006 return; ··· 1017 1018 } 1018 1019 1019 1020 scoped_guard(raw_spinlock_irq, &desc->lock) { 1020 - /* 1021 - * This code is triggered unconditionally. Check the affinity 1022 - * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out. 1023 - */ 1024 - if (cpumask_available(desc->irq_common_data.affinity)) { 1025 - const struct cpumask *m; 1021 + const struct cpumask *m; 1026 1022 1027 - m = irq_data_get_effective_affinity_mask(&desc->irq_data); 1028 - cpumask_copy(mask, m); 1029 - valid = true; 1030 - } 1023 + m = irq_data_get_effective_affinity_mask(&desc->irq_data); 1024 + cpumask_copy(mask, m); 1031 1025 } 1032 1026 1033 - if (valid) 1034 - set_cpus_allowed_ptr(current, mask); 1027 + set_cpus_allowed_ptr(current, mask); 1035 1028 free_cpumask_var(mask); 1036 1029 } 1037 1030 #else ··· 1230 1239 1231 1240 irq_thread_set_ready(desc, action); 1232 1241 1233 - sched_set_fifo(current); 1242 + if (action->handler == irq_forced_secondary_handler) 1243 + sched_set_fifo_secondary(current); 1244 + else 1245 + sched_set_fifo(current); 1234 1246 1235 1247 if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD, 1236 1248 &action->thread_flags)) ··· 1399 1405 * references an already freed task_struct. 1400 1406 */ 1401 1407 new->thread = get_task_struct(t); 1408 + 1402 1409 /* 1403 - * Tell the thread to set its affinity. This is 1404 - * important for shared interrupt handlers as we do 1405 - * not invoke setup_affinity() for the secondary 1406 - * handlers as everything is already set up. Even for 1407 - * interrupts marked with IRQF_NO_BALANCE this is 1408 - * correct as we want the thread to move to the cpu(s) 1409 - * on which the requesting code placed the interrupt. 1410 + * The affinity can not be established yet, but it will be once the 1411 + * interrupt is enabled. Delay and defer the actual setting to the 1412 + * thread itself once it is ready to run. In the meantime, prevent 1413 + * it from ever being re-affined directly by cpuset or 1414 + * housekeeping. The proper way to do it is to re-affine the whole 1415 + * vector. 1410 1416 */ 1411 - set_bit(IRQTF_AFFINITY, &new->thread_flags); 1417 + kthread_bind_mask(t, cpu_possible_mask); 1418 + 1419 + /* 1420 + * Ensure the thread adjusts the affinity once it reaches the 1421 + * thread function. 1422 + */ 1423 + new->thread_flags = BIT(IRQTF_AFFINITY); 1424 + 1412 1425 return 0; 1426 + } 1427 + 1428 + static bool valid_percpu_irqaction(struct irqaction *old, struct irqaction *new) 1429 + { 1430 + do { 1431 + if (cpumask_intersects(old->affinity, new->affinity) || 1432 + old->percpu_dev_id == new->percpu_dev_id) 1433 + return false; 1434 + 1435 + old = old->next; 1436 + } while (old); 1437 + 1438 + return true; 1413 1439 } 1414 1440 1415 1441 /* ··· 1452 1438 struct irqaction *old, **old_ptr; 1453 1439 unsigned long flags, thread_mask = 0; 1454 1440 int ret, nested, shared = 0; 1441 + bool per_cpu_devid; 1455 1442 1456 1443 if (!desc) 1457 1444 return -EINVAL; ··· 1461 1446 return -ENOSYS; 1462 1447 if (!try_module_get(desc->owner)) 1463 1448 return -ENODEV; 1449 + 1450 + per_cpu_devid = irq_settings_is_per_cpu_devid(desc); 1464 1451 1465 1452 new->irq = irq; 1466 1453 ··· 1571 1554 */ 1572 1555 unsigned int oldtype; 1573 1556 1574 - if (irq_is_nmi(desc)) { 1557 + if (irq_is_nmi(desc) && !per_cpu_devid) { 1575 1558 pr_err("Invalid attempt to share NMI for %s (irq %d) on irqchip %s.\n", 1559 + new->name, irq, desc->irq_data.chip->name); 1560 + ret = -EINVAL; 1561 + goto out_unlock; 1562 + } 1563 + 1564 + if (per_cpu_devid && !valid_percpu_irqaction(old, new)) { 1565 + pr_err("Overlapping affinities for %s (irq %d) on irqchip %s.\n", 1576 1566 new->name, irq, desc->irq_data.chip->name); 1577 1567 ret = -EINVAL; 1578 1568 goto out_unlock; ··· 1735 1711 if (!(new->flags & IRQF_NO_AUTOEN) && 1736 1712 irq_settings_can_autoenable(desc)) { 1737 1713 irq_startup(desc, IRQ_RESEND, IRQ_START_COND); 1738 - } else { 1714 + } else if (!per_cpu_devid) { 1739 1715 /* 1740 1716 * Shared interrupts do not go well with disabling 1741 1717 * auto enable. The sharing interrupt might request ··· 2370 2346 static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id) 2371 2347 { 2372 2348 struct irq_desc *desc = irq_to_desc(irq); 2373 - struct irqaction *action; 2349 + struct irqaction *action, **action_ptr; 2374 2350 2375 2351 WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); 2376 2352 ··· 2378 2354 return NULL; 2379 2355 2380 2356 scoped_guard(raw_spinlock_irqsave, &desc->lock) { 2381 - action = desc->action; 2382 - if (!action || action->percpu_dev_id != dev_id) { 2383 - WARN(1, "Trying to free already-free IRQ %d\n", irq); 2384 - return NULL; 2357 + action_ptr = &desc->action; 2358 + for (;;) { 2359 + action = *action_ptr; 2360 + 2361 + if (!action) { 2362 + WARN(1, "Trying to free already-free IRQ %d\n", irq); 2363 + return NULL; 2364 + } 2365 + 2366 + if (action->percpu_dev_id == dev_id) 2367 + break; 2368 + 2369 + action_ptr = &action->next; 2385 2370 } 2386 2371 2387 - if (!cpumask_empty(desc->percpu_enabled)) { 2388 - WARN(1, "percpu IRQ %d still enabled on CPU%d!\n", 2389 - irq, cpumask_first(desc->percpu_enabled)); 2372 + if (cpumask_intersects(desc->percpu_enabled, action->affinity)) { 2373 + WARN(1, "percpu IRQ %d still enabled on CPU%d!\n", irq, 2374 + cpumask_first_and(desc->percpu_enabled, action->affinity)); 2390 2375 return NULL; 2391 2376 } 2392 2377 2393 2378 /* Found it - now remove it from the list of entries: */ 2394 - desc->action = NULL; 2395 - desc->istate &= ~IRQS_NMI; 2379 + *action_ptr = action->next; 2380 + 2381 + /* Demote from NMI if we killed the last action */ 2382 + if (!desc->action) 2383 + desc->istate &= ~IRQS_NMI; 2396 2384 } 2397 2385 2398 2386 unregister_handler_proc(irq, action); ··· 2478 2442 return retval; 2479 2443 } 2480 2444 2445 + static 2446 + struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags, 2447 + const char *devname, const cpumask_t *affinity, 2448 + void __percpu *dev_id) 2449 + { 2450 + struct irqaction *action; 2451 + 2452 + if (!affinity) 2453 + affinity = cpu_possible_mask; 2454 + 2455 + action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 2456 + if (!action) 2457 + return NULL; 2458 + 2459 + action->handler = handler; 2460 + action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND; 2461 + action->name = devname; 2462 + action->percpu_dev_id = dev_id; 2463 + action->affinity = affinity; 2464 + 2465 + /* 2466 + * We allow some form of sharing for non-overlapping affinity 2467 + * masks. Obviously, covering all CPUs prevents any sharing in 2468 + * the first place. 2469 + */ 2470 + if (!cpumask_equal(affinity, cpu_possible_mask)) 2471 + action->flags |= IRQF_SHARED; 2472 + 2473 + return action; 2474 + } 2475 + 2481 2476 /** 2482 2477 * __request_percpu_irq - allocate a percpu interrupt line 2483 2478 * @irq: Interrupt line to allocate 2484 2479 * @handler: Function to be called when the IRQ occurs. 2485 2480 * @flags: Interrupt type flags (IRQF_TIMER only) 2486 2481 * @devname: An ascii name for the claiming device 2482 + * @affinity: A cpumask describing the target CPUs for this interrupt 2487 2483 * @dev_id: A percpu cookie passed back to the handler function 2488 2484 * 2489 - * This call allocates interrupt resources and enables the interrupt on the 2490 - * local CPU. If the interrupt is supposed to be enabled on other CPUs, it 2491 - * has to be done on each CPU using enable_percpu_irq(). 2485 + * This call allocates interrupt resources, but doesn't enable the interrupt 2486 + * on any CPU, as all percpu-devid interrupts are flagged with IRQ_NOAUTOEN. 2487 + * It has to be done on each CPU using enable_percpu_irq(). 2492 2488 * 2493 2489 * @dev_id must be globally unique. It is a per-cpu variable, and 2494 2490 * the handler gets called with the interrupted CPU's instance of ··· 2528 2460 */ 2529 2461 int __request_percpu_irq(unsigned int irq, irq_handler_t handler, 2530 2462 unsigned long flags, const char *devname, 2531 - void __percpu *dev_id) 2463 + const cpumask_t *affinity, void __percpu *dev_id) 2532 2464 { 2533 2465 struct irqaction *action; 2534 2466 struct irq_desc *desc; ··· 2545 2477 if (flags && flags != IRQF_TIMER) 2546 2478 return -EINVAL; 2547 2479 2548 - action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 2480 + action = create_percpu_irqaction(handler, flags, devname, affinity, dev_id); 2549 2481 if (!action) 2550 2482 return -ENOMEM; 2551 - 2552 - action->handler = handler; 2553 - action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND; 2554 - action->name = devname; 2555 - action->percpu_dev_id = dev_id; 2556 2483 2557 2484 retval = irq_chip_pm_get(&desc->irq_data); 2558 2485 if (retval < 0) { ··· 2571 2508 * @irq: Interrupt line to allocate 2572 2509 * @handler: Function to be called when the IRQ occurs. 2573 2510 * @name: An ascii name for the claiming device 2511 + * @affinity: A cpumask describing the target CPUs for this interrupt 2574 2512 * @dev_id: A percpu cookie passed back to the handler function 2575 2513 * 2576 2514 * This call allocates interrupt resources for a per CPU NMI. Per CPU NMIs ··· 2588 2524 * If the interrupt line cannot be used to deliver NMIs, function 2589 2525 * will fail returning a negative value. 2590 2526 */ 2591 - int request_percpu_nmi(unsigned int irq, irq_handler_t handler, 2592 - const char *name, void __percpu *dev_id) 2527 + int request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name, 2528 + const struct cpumask *affinity, void __percpu *dev_id) 2593 2529 { 2594 2530 struct irqaction *action; 2595 2531 struct irq_desc *desc; ··· 2606 2542 !irq_supports_nmi(desc)) 2607 2543 return -EINVAL; 2608 2544 2609 - /* The line cannot already be NMI */ 2610 - if (irq_is_nmi(desc)) 2545 + /* The line cannot be NMI already if the new request covers all CPUs */ 2546 + if (irq_is_nmi(desc) && 2547 + (!affinity || cpumask_equal(affinity, cpu_possible_mask))) 2611 2548 return -EINVAL; 2612 2549 2613 - action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 2550 + action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING, 2551 + name, affinity, dev_id); 2614 2552 if (!action) 2615 2553 return -ENOMEM; 2616 - 2617 - action->handler = handler; 2618 - action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND | IRQF_NO_THREAD 2619 - | IRQF_NOBALANCING; 2620 - action->name = name; 2621 - action->percpu_dev_id = dev_id; 2622 2554 2623 2555 retval = irq_chip_pm_get(&desc->irq_data); 2624 2556 if (retval < 0)
+2
kernel/irq/proc.c
··· 48 48 struct irq_desc *desc = irq_to_desc((long)m->private); 49 49 const struct cpumask *mask; 50 50 51 + guard(raw_spinlock_irq)(&desc->lock); 52 + 51 53 switch (type) { 52 54 case AFFINITY: 53 55 case AFFINITY_LIST:
+13
kernel/sched/syscalls.c
··· 824 824 } 825 825 EXPORT_SYMBOL_GPL(sched_set_fifo_low); 826 826 827 + /* 828 + * Used when the primary interrupt handler is forced into a thread, in addition 829 + * to the (always threaded) secondary handler. The secondary handler gets a 830 + * slightly lower priority so that the primary handler can preempt it, thereby 831 + * emulating the behavior of a non-PREEMPT_RT system where the primary handler 832 + * runs in hard interrupt context. 833 + */ 834 + void sched_set_fifo_secondary(struct task_struct *p) 835 + { 836 + struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 - 1 }; 837 + WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0); 838 + } 839 + 827 840 void sched_set_normal(struct task_struct *p, int nice) 828 841 { 829 842 struct sched_attr attr = {