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-drivers-2025-07-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull interrupt chip driver updates from Thomas Gleixner:

- Add support of forced affinity setting to yet offline CPUs for the
MIPS-GIC to ensure that the affinity of per CPU interrupts can be set
during the early bringup phase of a secondary CPU in the hotplug code
before the CPU is set online and interrupts are enabled

- Add support for the MIPS (RISC-V !?!?) P8700 SoC in the ACLINT_SSWI
interrupt chip

- Make the interrupt routing to RISV-V harts specification compliant so
it supports arbitrary hart indices

- Add a command line parameter and related handling to disable the
generic RISCV IMSIC mechanism on platforms which use a trap-emulated
IMSIC. Unfortunatly this is required because there is no mechanism
available to discover this programatically.

- Enable wakeup sources on the Renesas RZV2H driver

- Convert interrupt chip drivers, which use a open coded variant of
msi_create_parent_irq_domain() to use the new functionality

- Convert interrupt chip drivers, which use the old style two level
implementation of MSI support over to the MSI parent mechanism to
prepare for removing at least one of the three PCI/MSI backend
variants.

- The usual cleanups and improvements all over the place

* tag 'irq-drivers-2025-07-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (28 commits)
irqchip/renesas-irqc: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
irqchip/renesas-intc-irqpin: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
irqchip/riscv-imsic: Add kernel parameter to disable IPIs
irqchip/gic-v3: Fix GICD_CTLR register naming
irqchip/ls-scfg-msi: Fix NULL dereference in error handling
irqchip/ls-scfg-msi: Switch to use msi_create_parent_irq_domain()
irqchip/armada-370-xp: Switch to msi_create_parent_irq_domain()
irqchip/alpine-msi: Switch to msi_create_parent_irq_domain()
irqchip/alpine-msi: Convert to __free
irqchip/alpine-msi: Convert to lock guards
irqchip/alpine-msi: Clean up whitespace style
irqchip/sg2042-msi: Switch to msi_create_parent_irq_domain()
irqchip/loongson-pch-msi.c: Switch to msi_create_parent_irq_domain()
irqchip/imx-mu-msi: Convert to msi_create_parent_irq_domain() helper
irqchip/riscv-imsic: Convert to msi_create_parent_irq_domain() helper
irqchip/bcm2712-mip: Switch to msi_create_parent_irq_domain()
irqdomain: Add device pointer to irq_domain_info and msi_domain_info
irqchip/renesas-rzv2h: Remove unneeded includes
irqchip/renesas-rzv2h: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND
irqchip/aslint-sswi: Resolve hart index
...

+398 -314
+7
Documentation/admin-guide/kernel-parameters.txt
··· 2538 2538 requires the kernel to be built with 2539 2539 CONFIG_ARM64_PSEUDO_NMI. 2540 2540 2541 + irqchip.riscv_imsic_noipi 2542 + [RISC-V,EARLY] 2543 + Force the kernel to not use IMSIC software injected MSIs 2544 + as IPIs. Intended for system where IMSIC is trap-n-emulated, 2545 + and thus want to reduce MMIO traps when triggering IPIs 2546 + to multiple harts. 2547 + 2541 2548 irqfixup [HW] 2542 2549 When an interrupt is not handled search all handlers 2543 2550 for it. Intended to get systems with badly broken
+55 -9
Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
··· 4 4 $id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-sswi.yaml# 5 5 $schema: http://devicetree.org/meta-schemas/core.yaml# 6 6 7 - title: T-HEAD C900 ACLINT Supervisor-level Software Interrupt Device 7 + title: ACLINT Supervisor-level Software Interrupt Device 8 8 9 9 maintainers: 10 10 - Inochi Amaoto <inochiama@outlook.com> 11 11 12 12 description: 13 - The SSWI device is a part of the THEAD ACLINT device. It provides 14 - supervisor-level IPI functionality for a set of HARTs on a THEAD 15 - platform. It provides a register to set an IPI (SETSSIP) for each 16 - HART connected to the SSWI device. 13 + The SSWI device is a part of the ACLINT device. It provides 14 + supervisor-level IPI functionality for a set of HARTs on a supported 15 + platforms. It provides a register to set an IPI (SETSSIP) for each 16 + HART connected to the SSWI device. See draft specification 17 + https://github.com/riscvarchive/riscv-aclint 18 + 19 + Following variants of the SSWI ACLINT supported, using dedicated 20 + compatible string 21 + - THEAD C900 22 + - MIPS P8700 17 23 18 24 properties: 19 25 compatible: 20 - items: 21 - - enum: 22 - - sophgo,sg2044-aclint-sswi 23 - - const: thead,c900-aclint-sswi 26 + oneOf: 27 + - items: 28 + - enum: 29 + - sophgo,sg2044-aclint-sswi 30 + - const: thead,c900-aclint-sswi 31 + - items: 32 + - const: mips,p8700-aclint-sswi 24 33 25 34 reg: 26 35 maxItems: 1 ··· 43 34 minItems: 1 44 35 maxItems: 4095 45 36 37 + riscv,hart-indexes: 38 + $ref: /schemas/types.yaml#/definitions/uint32-array 39 + minItems: 1 40 + maxItems: 4095 41 + description: 42 + A list of hart indexes that APLIC should use to address each hart 43 + that is mentioned in the "interrupts-extended" 44 + 46 45 additionalProperties: false 47 46 48 47 required: ··· 60 43 - interrupt-controller 61 44 - interrupts-extended 62 45 46 + allOf: 47 + - if: 48 + properties: 49 + compatible: 50 + contains: 51 + const: mips,p8700-aclint-sswi 52 + then: 53 + required: 54 + - riscv,hart-indexes 55 + else: 56 + properties: 57 + riscv,hart-indexes: false 58 + 63 59 examples: 64 60 - | 61 + //Example 1 65 62 interrupt-controller@94000000 { 66 63 compatible = "sophgo,sg2044-aclint-sswi", "thead,c900-aclint-sswi"; 67 64 reg = <0x94000000 0x00004000>; ··· 86 55 <&cpu3intc 1>, 87 56 <&cpu4intc 1>; 88 57 }; 58 + 59 + - | 60 + //Example 2 61 + interrupt-controller@94000000 { 62 + compatible = "mips,p8700-aclint-sswi"; 63 + reg = <0x94000000 0x00004000>; 64 + #interrupt-cells = <0>; 65 + interrupt-controller; 66 + interrupts-extended = <&cpu1intc 1>, 67 + <&cpu2intc 1>, 68 + <&cpu3intc 1>, 69 + <&cpu4intc 1>; 70 + riscv,hart-indexes = <0x0 0x1 0x10 0x11>; 71 + }; 72 + 89 73 ...
+2
arch/riscv/include/asm/irq.h
··· 22 22 void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void)); 23 23 24 24 struct fwnode_handle *riscv_get_intc_hwnode(void); 25 + int riscv_get_hart_index(struct fwnode_handle *fwnode, u32 logical_index, 26 + u32 *hart_index); 25 27 26 28 #ifdef CONFIG_ACPI 27 29
+34
arch/riscv/kernel/irq.c
··· 32 32 } 33 33 EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode); 34 34 35 + /** 36 + * riscv_get_hart_index() - get hart index for interrupt delivery 37 + * @fwnode: interrupt controller node 38 + * @logical_index: index within the "interrupts-extended" property 39 + * @hart_index: filled with the hart index to use 40 + * 41 + * RISC-V uses term "hart index" for its interrupt controllers, for the 42 + * purpose of the interrupt routing to destination harts. 43 + * It may be arbitrary numbers assigned to each destination hart in context 44 + * of the particular interrupt domain. 45 + * 46 + * These numbers encoded in the optional property "riscv,hart-indexes" 47 + * that should contain hart index for each interrupt destination in the same 48 + * order as in the "interrupts-extended" property. If this property 49 + * not exist, it assumed equal to the logical index, i.e. index within the 50 + * "interrupts-extended" property. 51 + * 52 + * Return: error code 53 + */ 54 + int riscv_get_hart_index(struct fwnode_handle *fwnode, u32 logical_index, 55 + u32 *hart_index) 56 + { 57 + static const char *prop_hart_index = "riscv,hart-indexes"; 58 + struct device_node *np = to_of_node(fwnode); 59 + 60 + if (!np || !of_property_present(np, prop_hart_index)) { 61 + *hart_index = logical_index; 62 + return 0; 63 + } 64 + 65 + return of_property_read_u32_index(np, prop_hart_index, 66 + logical_index, hart_index); 67 + } 68 + 35 69 #ifdef CONFIG_IRQ_STACKS 36 70 #include <asm/irq_stack.h> 37 71
+14 -4
drivers/irqchip/Kconfig
··· 80 80 bool 81 81 select GENERIC_IRQ_CHIP 82 82 select PCI_MSI if PCI 83 + select IRQ_MSI_LIB if PCI 83 84 select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 84 85 85 86 config ALPINE_MSI 86 87 bool 87 88 depends on PCI 88 89 select PCI_MSI 90 + select IRQ_MSI_LIB 89 91 select GENERIC_IRQ_CHIP 90 92 91 93 config AL_FIC ··· 437 435 def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE 438 436 select IRQ_MSI_IOMMU 439 437 depends on PCI_MSI 438 + select IRQ_MSI_LIB 440 439 441 440 config PARTITION_PERCPU 442 441 bool ··· 638 635 639 636 If you don't know what to do here, say Y. 640 637 641 - config THEAD_C900_ACLINT_SSWI 642 - bool "THEAD C9XX ACLINT S-mode IPI Interrupt Controller" 638 + config ACLINT_SSWI 639 + bool "RISC-V ACLINT S-mode IPI Interrupt Controller" 643 640 depends on RISCV 644 641 depends on SMP 645 642 select IRQ_DOMAIN_HIERARCHY 646 643 select GENERIC_IRQ_IPI_MUX 647 644 help 648 - This enables support for T-HEAD specific ACLINT SSWI device 649 - support. 645 + This enables support for variants of the RISC-V ACLINT-SSWI device. 646 + Supported variants are: 647 + - T-HEAD, with compatible "thead,c900-aclint-sswi" 648 + - MIPS P8700, with compatible "mips,p8700-aclint-sswi" 650 649 651 650 If you don't know what to do here, say Y. 651 + 652 + # Backwards compatibility so oldconfig does not drop it. 653 + config THEAD_C900_ACLINT_SSWI 654 + bool 655 + select ACLINT_SSWI 652 656 653 657 config EXYNOS_IRQ_COMBINER 654 658 bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST
+1 -1
drivers/irqchip/Makefile
··· 105 105 obj-$(CONFIG_RISCV_IMSIC) += irq-riscv-imsic-state.o irq-riscv-imsic-early.o irq-riscv-imsic-platform.o 106 106 obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o 107 107 obj-$(CONFIG_STARFIVE_JH8100_INTC) += irq-starfive-jh8100-intc.o 108 - obj-$(CONFIG_THEAD_C900_ACLINT_SSWI) += irq-thead-c900-aclint-sswi.o 108 + obj-$(CONFIG_ACLINT_SSWI) += irq-aclint-sswi.o 109 109 obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o 110 110 obj-$(CONFIG_IMX_INTMUX) += irq-imx-intmux.o 111 111 obj-$(CONFIG_IMX_MU_MSI) += irq-imx-mu-msi.o
+56 -99
drivers/irqchip/irq-alpine-msi.c
··· 14 14 15 15 #include <linux/irqchip.h> 16 16 #include <linux/irqchip/arm-gic.h> 17 + #include <linux/irqchip/irq-msi-lib.h> 17 18 #include <linux/msi.h> 18 19 #include <linux/of.h> 19 20 #include <linux/of_address.h> ··· 30 29 #define ALPINE_MSIX_SPI_TARGET_CLUSTER0 BIT(16) 31 30 32 31 struct alpine_msix_data { 33 - spinlock_t msi_map_lock; 34 - phys_addr_t addr; 35 - u32 spi_first; /* The SGI number that MSIs start */ 36 - u32 num_spis; /* The number of SGIs for MSIs */ 37 - unsigned long *msi_map; 38 - }; 39 - 40 - static void alpine_msix_mask_msi_irq(struct irq_data *d) 41 - { 42 - pci_msi_mask_irq(d); 43 - irq_chip_mask_parent(d); 44 - } 45 - 46 - static void alpine_msix_unmask_msi_irq(struct irq_data *d) 47 - { 48 - pci_msi_unmask_irq(d); 49 - irq_chip_unmask_parent(d); 50 - } 51 - 52 - static struct irq_chip alpine_msix_irq_chip = { 53 - .name = "MSIx", 54 - .irq_mask = alpine_msix_mask_msi_irq, 55 - .irq_unmask = alpine_msix_unmask_msi_irq, 56 - .irq_eoi = irq_chip_eoi_parent, 57 - .irq_set_affinity = irq_chip_set_affinity_parent, 32 + spinlock_t msi_map_lock; 33 + phys_addr_t addr; 34 + u32 spi_first; /* The SGI number that MSIs start */ 35 + u32 num_spis; /* The number of SGIs for MSIs */ 36 + unsigned long *msi_map; 58 37 }; 59 38 60 39 static int alpine_msix_allocate_sgi(struct alpine_msix_data *priv, int num_req) 61 40 { 62 41 int first; 63 42 64 - spin_lock(&priv->msi_map_lock); 65 - 66 - first = bitmap_find_next_zero_area(priv->msi_map, priv->num_spis, 0, 67 - num_req, 0); 68 - if (first >= priv->num_spis) { 69 - spin_unlock(&priv->msi_map_lock); 43 + guard(spinlock)(&priv->msi_map_lock); 44 + first = bitmap_find_next_zero_area(priv->msi_map, priv->num_spis, 0, num_req, 0); 45 + if (first >= priv->num_spis) 70 46 return -ENOSPC; 71 - } 72 47 73 48 bitmap_set(priv->msi_map, first, num_req); 74 - 75 - spin_unlock(&priv->msi_map_lock); 76 - 77 49 return priv->spi_first + first; 78 50 } 79 51 80 - static void alpine_msix_free_sgi(struct alpine_msix_data *priv, unsigned sgi, 81 - int num_req) 52 + static void alpine_msix_free_sgi(struct alpine_msix_data *priv, unsigned int sgi, int num_req) 82 53 { 83 54 int first = sgi - priv->spi_first; 84 55 85 - spin_lock(&priv->msi_map_lock); 86 - 56 + guard(spinlock)(&priv->msi_map_lock); 87 57 bitmap_clear(priv->msi_map, first, num_req); 88 - 89 - spin_unlock(&priv->msi_map_lock); 90 58 } 91 59 92 - static void alpine_msix_compose_msi_msg(struct irq_data *data, 93 - struct msi_msg *msg) 60 + static void alpine_msix_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 94 61 { 95 62 struct alpine_msix_data *priv = irq_data_get_irq_chip_data(data); 96 63 phys_addr_t msg_addr = priv->addr; 97 64 98 65 msg_addr |= (data->hwirq << 3); 99 - 100 66 msg->address_hi = upper_32_bits(msg_addr); 101 67 msg->address_lo = lower_32_bits(msg_addr); 102 68 msg->data = 0; 103 69 } 104 - 105 - static struct msi_domain_info alpine_msix_domain_info = { 106 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 107 - MSI_FLAG_PCI_MSIX, 108 - .chip = &alpine_msix_irq_chip, 109 - }; 110 70 111 71 static struct irq_chip middle_irq_chip = { 112 72 .name = "alpine_msix_middle", ··· 78 116 .irq_compose_msi_msg = alpine_msix_compose_msi_msg, 79 117 }; 80 118 81 - static int alpine_msix_gic_domain_alloc(struct irq_domain *domain, 82 - unsigned int virq, int sgi) 119 + static int alpine_msix_gic_domain_alloc(struct irq_domain *domain, unsigned int virq, int sgi) 83 120 { 84 121 struct irq_fwspec fwspec; 85 122 struct irq_data *d; ··· 99 138 100 139 d = irq_domain_get_irq_data(domain->parent, virq); 101 140 d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING); 102 - 103 141 return 0; 104 142 } 105 143 106 - static int alpine_msix_middle_domain_alloc(struct irq_domain *domain, 107 - unsigned int virq, 144 + static int alpine_msix_middle_domain_alloc(struct irq_domain *domain, unsigned int virq, 108 145 unsigned int nr_irqs, void *args) 109 146 { 110 147 struct alpine_msix_data *priv = domain->host_data; ··· 120 161 irq_domain_set_hwirq_and_chip(domain, virq + i, sgi + i, 121 162 &middle_irq_chip, priv); 122 163 } 123 - 124 164 return 0; 125 165 126 166 err_sgi: ··· 128 170 return err; 129 171 } 130 172 131 - static void alpine_msix_middle_domain_free(struct irq_domain *domain, 132 - unsigned int virq, 173 + static void alpine_msix_middle_domain_free(struct irq_domain *domain, unsigned int virq, 133 174 unsigned int nr_irqs) 134 175 { 135 176 struct irq_data *d = irq_domain_get_irq_data(domain, virq); ··· 139 182 } 140 183 141 184 static const struct irq_domain_ops alpine_msix_middle_domain_ops = { 185 + .select = msi_lib_irq_domain_select, 142 186 .alloc = alpine_msix_middle_domain_alloc, 143 187 .free = alpine_msix_middle_domain_free, 144 188 }; 145 189 146 - static int alpine_msix_init_domains(struct alpine_msix_data *priv, 147 - struct device_node *node) 190 + #define ALPINE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 191 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 192 + MSI_FLAG_PCI_MSI_MASK_PARENT) 193 + 194 + #define ALPINE_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 195 + MSI_FLAG_PCI_MSIX) 196 + 197 + static struct msi_parent_ops alpine_msi_parent_ops = { 198 + .supported_flags = ALPINE_MSI_FLAGS_SUPPORTED, 199 + .required_flags = ALPINE_MSI_FLAGS_REQUIRED, 200 + .chip_flags = MSI_CHIP_FLAG_SET_EOI, 201 + .bus_select_token = DOMAIN_BUS_NEXUS, 202 + .bus_select_mask = MATCH_PCI_MSI, 203 + .prefix = "ALPINE-", 204 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 205 + }; 206 + 207 + static int alpine_msix_init_domains(struct alpine_msix_data *priv, struct device_node *node) 148 208 { 149 - struct irq_domain *middle_domain, *msi_domain, *gic_domain; 209 + struct irq_domain_info info = { 210 + .fwnode = of_fwnode_handle(node), 211 + .ops = &alpine_msix_middle_domain_ops, 212 + .host_data = priv, 213 + }; 150 214 struct device_node *gic_node; 151 215 152 216 gic_node = of_irq_find_parent(node); ··· 176 198 return -ENODEV; 177 199 } 178 200 179 - gic_domain = irq_find_host(gic_node); 201 + info.parent = irq_find_host(gic_node); 180 202 of_node_put(gic_node); 181 - if (!gic_domain) { 203 + if (!info.parent) { 182 204 pr_err("Failed to find the GIC domain\n"); 183 205 return -ENXIO; 184 206 } 185 207 186 - middle_domain = irq_domain_create_hierarchy(gic_domain, 0, 0, NULL, 187 - &alpine_msix_middle_domain_ops, priv); 188 - if (!middle_domain) { 189 - pr_err("Failed to create the MSIX middle domain\n"); 190 - return -ENOMEM; 191 - } 192 - 193 - msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node), 194 - &alpine_msix_domain_info, 195 - middle_domain); 196 - if (!msi_domain) { 208 + if (!msi_create_parent_irq_domain(&info, &alpine_msi_parent_ops)) { 197 209 pr_err("Failed to create MSI domain\n"); 198 - irq_domain_remove(middle_domain); 199 210 return -ENOMEM; 200 211 } 201 - 202 212 return 0; 203 213 } 204 214 205 - static int alpine_msix_init(struct device_node *node, 206 - struct device_node *parent) 215 + static int alpine_msix_init(struct device_node *node, struct device_node *parent) 207 216 { 208 - struct alpine_msix_data *priv; 217 + struct alpine_msix_data *priv __free(kfree) = kzalloc(sizeof(*priv), GFP_KERNEL); 209 218 struct resource res; 210 219 int ret; 211 220 212 - priv = kzalloc(sizeof(*priv), GFP_KERNEL); 213 221 if (!priv) 214 222 return -ENOMEM; 215 223 ··· 204 240 ret = of_address_to_resource(node, 0, &res); 205 241 if (ret) { 206 242 pr_err("Failed to allocate resource\n"); 207 - goto err_priv; 243 + return ret; 208 244 } 209 245 210 246 /* ··· 219 255 220 256 if (of_property_read_u32(node, "al,msi-base-spi", &priv->spi_first)) { 221 257 pr_err("Unable to parse MSI base\n"); 222 - ret = -EINVAL; 223 - goto err_priv; 258 + return -EINVAL; 224 259 } 225 260 226 261 if (of_property_read_u32(node, "al,msi-num-spis", &priv->num_spis)) { 227 262 pr_err("Unable to parse MSI numbers\n"); 228 - ret = -EINVAL; 229 - goto err_priv; 263 + return -EINVAL; 230 264 } 231 265 232 - priv->msi_map = bitmap_zalloc(priv->num_spis, GFP_KERNEL); 233 - if (!priv->msi_map) { 234 - ret = -ENOMEM; 235 - goto err_priv; 236 - } 266 + unsigned long *msi_map __free(kfree) = bitmap_zalloc(priv->num_spis, GFP_KERNEL); 237 267 238 - pr_debug("Registering %d msixs, starting at %d\n", 239 - priv->num_spis, priv->spi_first); 268 + if (!msi_map) 269 + return -ENOMEM; 270 + priv->msi_map = msi_map; 271 + 272 + pr_debug("Registering %d msixs, starting at %d\n", priv->num_spis, priv->spi_first); 240 273 241 274 ret = alpine_msix_init_domains(priv, node); 242 275 if (ret) 243 - goto err_map; 276 + return ret; 244 277 278 + retain_and_null_ptr(priv); 279 + retain_and_null_ptr(msi_map); 245 280 return 0; 246 - 247 - err_map: 248 - bitmap_free(priv->msi_map); 249 - err_priv: 250 - kfree(priv); 251 - return ret; 252 281 } 253 282 IRQCHIP_DECLARE(alpine_msix, "al,alpine-msix", alpine_msix_init);
+25 -23
drivers/irqchip/irq-armada-370-xp.c
··· 20 20 #include <linux/interrupt.h> 21 21 #include <linux/irqchip.h> 22 22 #include <linux/irqchip/chained_irq.h> 23 + #include <linux/irqchip/irq-msi-lib.h> 23 24 #include <linux/cpu.h> 24 25 #include <linux/io.h> 25 26 #include <linux/of_address.h> ··· 157 156 * @parent_irq: parent IRQ if MPIC is not top-level interrupt controller 158 157 * @domain: MPIC main interrupt domain 159 158 * @ipi_domain: IPI domain 160 - * @msi_domain: MSI domain 161 159 * @msi_inner_domain: MSI inner domain 162 160 * @msi_used: bitmap of used MSI numbers 163 161 * @msi_lock: mutex serializing access to @msi_used ··· 176 176 struct irq_domain *ipi_domain; 177 177 #endif 178 178 #ifdef CONFIG_PCI_MSI 179 - struct irq_domain *msi_domain; 180 179 struct irq_domain *msi_inner_domain; 181 180 DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR); 182 181 struct mutex msi_lock; ··· 232 233 } 233 234 234 235 #ifdef CONFIG_PCI_MSI 235 - 236 - static struct irq_chip mpic_msi_irq_chip = { 237 - .name = "MPIC MSI", 238 - .irq_mask = pci_msi_mask_irq, 239 - .irq_unmask = pci_msi_unmask_irq, 240 - }; 241 - 242 - static struct msi_domain_info mpic_msi_domain_info = { 243 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 244 - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), 245 - .chip = &mpic_msi_irq_chip, 246 - }; 247 236 248 237 static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) 249 238 { ··· 301 314 } 302 315 303 316 static const struct irq_domain_ops mpic_msi_domain_ops = { 317 + .select = msi_lib_irq_domain_select, 304 318 .alloc = mpic_msi_alloc, 305 319 .free = mpic_msi_free, 306 320 }; ··· 318 330 /* Unmask local doorbell interrupt */ 319 331 writel(1, mpic->per_cpu + MPIC_INT_CLEAR_MASK); 320 332 } 333 + 334 + #define MPIC_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 335 + MSI_FLAG_USE_DEF_CHIP_OPS) 336 + #define MPIC_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \ 337 + MSI_FLAG_PCI_MSIX | \ 338 + MSI_GENERIC_FLAGS_MASK) 339 + 340 + static const struct msi_parent_ops mpic_msi_parent_ops = { 341 + .required_flags = MPIC_MSI_FLAGS_REQUIRED, 342 + .supported_flags = MPIC_MSI_FLAGS_SUPPORTED, 343 + .bus_select_token = DOMAIN_BUS_NEXUS, 344 + .bus_select_mask = MATCH_PCI_MSI, 345 + .prefix = "MPIC-", 346 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 347 + }; 321 348 322 349 static int __init mpic_msi_init(struct mpic *mpic, struct device_node *node, 323 350 phys_addr_t main_int_phys_base) ··· 351 348 mpic->msi_doorbell_mask = PCI_MSI_FULL_DOORBELL_MASK; 352 349 } 353 350 354 - mpic->msi_inner_domain = irq_domain_create_linear(NULL, mpic->msi_doorbell_size, 355 - &mpic_msi_domain_ops, mpic); 351 + struct irq_domain_info info = { 352 + .fwnode = of_fwnode_handle(node), 353 + .ops = &mpic_msi_domain_ops, 354 + .host_data = mpic, 355 + .size = mpic->msi_doorbell_size, 356 + }; 357 + 358 + mpic->msi_inner_domain = msi_create_parent_irq_domain(&info, &mpic_msi_parent_ops); 356 359 if (!mpic->msi_inner_domain) 357 360 return -ENOMEM; 358 - 359 - mpic->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node), &mpic_msi_domain_info, 360 - mpic->msi_inner_domain); 361 - if (!mpic->msi_domain) { 362 - irq_domain_remove(mpic->msi_inner_domain); 363 - return -ENOMEM; 364 - } 365 361 366 362 mpic_msi_reenable_percpu(mpic); 367 363
+9 -9
drivers/irqchip/irq-bcm2712-mip.c
··· 172 172 173 173 static int mip_init_domains(struct mip_priv *mip, struct device_node *np) 174 174 { 175 - struct irq_domain *middle; 175 + struct irq_domain_info info = { 176 + .fwnode = of_fwnode_handle(np), 177 + .ops = &mip_middle_domain_ops, 178 + .host_data = mip, 179 + .size = mip->num_msis, 180 + .parent = mip->parent, 181 + .dev = mip->dev, 182 + }; 176 183 177 - middle = irq_domain_create_hierarchy(mip->parent, 0, mip->num_msis, of_fwnode_handle(np), 178 - &mip_middle_domain_ops, mip); 179 - if (!middle) 184 + if (!msi_create_parent_irq_domain(&info, &mip_msi_parent_ops)) 180 185 return -ENOMEM; 181 - 182 - irq_domain_update_bus_token(middle, DOMAIN_BUS_GENERIC_MSI); 183 - middle->dev = mip->dev; 184 - middle->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 185 - middle->msi_parent_ops = &mip_msi_parent_ops; 186 186 187 187 /* 188 188 * All MSI-X unmasked for the host, masked for the VPU, and edge-triggered.
+3 -3
drivers/irqchip/irq-gic-v3.c
··· 190 190 191 191 /* 192 192 * How priority values are used by the GIC depends on two things: 193 - * the security state of the GIC (controlled by the GICD_CTRL.DS bit) 193 + * the security state of the GIC (controlled by the GICD_CTLR.DS bit) 194 194 * and if Group 0 interrupts can be delivered to Linux in the non-secure 195 195 * world as FIQs (controlled by the SCR_EL3.FIQ bit). These affect the 196 196 * way priorities are presented in ICC_PMR_EL1 and in the distributor: 197 197 * 198 - * GICD_CTRL.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Distributor 198 + * GICD_CTLR.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Distributor 199 199 * ------------------------------------------------------- 200 200 * 1 | - | unchanged | unchanged 201 201 * ------------------------------------------------------- ··· 223 223 dist_prio_nmi = __gicv3_prio_to_ns(dist_prio_nmi); 224 224 } 225 225 226 - pr_info("GICD_CTRL.DS=%d, SCR_EL3.FIQ=%d\n", 226 + pr_info("GICD_CTLR.DS=%d, SCR_EL3.FIQ=%d\n", 227 227 cpus_have_security_disabled, 228 228 !cpus_have_group0); 229 229 }
+2 -2
drivers/irqchip/irq-imgpdc.c
··· 372 372 priv->syswake_irq = irq; 373 373 374 374 /* Set up an IRQ domain */ 375 - priv->domain = irq_domain_create_linear(of_fwnode_handle(node), 16, &irq_generic_chip_ops, 376 - priv); 375 + priv->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), 16, &irq_generic_chip_ops, 376 + priv); 377 377 if (unlikely(!priv->domain)) { 378 378 dev_err(&pdev->dev, "cannot add IRQ domain\n"); 379 379 return -ENOMEM;
+2 -2
drivers/irqchip/irq-imx-irqsteer.c
··· 212 212 /* steer all IRQs into configured channel */ 213 213 writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); 214 214 215 - data->domain = irq_domain_create_linear(of_fwnode_handle(np), data->reg_num * 32, 216 - &imx_irqsteer_domain_ops, data); 215 + data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32, 216 + &imx_irqsteer_domain_ops, data); 217 217 if (!data->domain) { 218 218 dev_err(&pdev->dev, "failed to create IRQ domain\n"); 219 219 ret = -ENOMEM;
+7 -7
drivers/irqchip/irq-imx-mu-msi.c
··· 223 223 224 224 static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct device *dev) 225 225 { 226 - struct fwnode_handle *fwnodes = dev_fwnode(dev); 226 + struct irq_domain_info info = { 227 + .ops = &imx_mu_msi_domain_ops, 228 + .fwnode = dev_fwnode(dev), 229 + .size = IMX_MU_CHANS, 230 + .host_data = msi_data, 231 + }; 227 232 struct irq_domain *parent; 228 233 229 234 /* Initialize MSI domain parent */ 230 - parent = irq_domain_create_linear(fwnodes, IMX_MU_CHANS, 231 - &imx_mu_msi_domain_ops, msi_data); 235 + parent = msi_create_parent_irq_domain(&info, &imx_mu_msi_parent_ops); 232 236 if (!parent) { 233 237 dev_err(dev, "failed to create IRQ domain\n"); 234 238 return -ENOMEM; 235 239 } 236 - 237 - irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 238 240 parent->dev = parent->pm_dev = dev; 239 - parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 240 - parent->msi_parent_ops = &imx_mu_msi_parent_ops; 241 241 return 0; 242 242 } 243 243
+2 -2
drivers/irqchip/irq-keystone.c
··· 157 157 kirq->chip.irq_mask = keystone_irq_setmask; 158 158 kirq->chip.irq_unmask = keystone_irq_unmask; 159 159 160 - kirq->irqd = irq_domain_create_linear(of_fwnode_handle(np), KEYSTONE_N_IRQ, 161 - &keystone_irq_ops, kirq); 160 + kirq->irqd = irq_domain_create_linear(dev_fwnode(dev), KEYSTONE_N_IRQ, &keystone_irq_ops, 161 + kirq); 162 162 if (!kirq->irqd) { 163 163 dev_err(dev, "IRQ domain registration failed\n"); 164 164 return -ENODEV;
+9 -14
drivers/irqchip/irq-loongson-pch-msi.c
··· 153 153 .init_dev_msi_info = msi_lib_init_dev_msi_info, 154 154 }; 155 155 156 - static int pch_msi_init_domains(struct pch_msi_data *priv, 157 - struct irq_domain *parent, 156 + static int pch_msi_init_domains(struct pch_msi_data *priv, struct irq_domain *parent, 158 157 struct fwnode_handle *domain_handle) 159 158 { 160 - struct irq_domain *middle_domain; 159 + struct irq_domain_info info = { 160 + .ops = &pch_msi_middle_domain_ops, 161 + .size = priv->num_irqs, 162 + .parent = parent, 163 + .host_data = priv, 164 + .fwnode = domain_handle, 165 + }; 161 166 162 - middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs, 163 - domain_handle, 164 - &pch_msi_middle_domain_ops, 165 - priv); 166 - if (!middle_domain) { 167 + if (!msi_create_parent_irq_domain(&info, &pch_msi_parent_ops)) { 167 168 pr_err("Failed to create the MSI middle domain\n"); 168 169 return -ENOMEM; 169 170 } 170 - 171 - irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); 172 - 173 - middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 174 - middle_domain->msi_parent_ops = &pch_msi_parent_ops; 175 - 176 171 return 0; 177 172 } 178 173
+21 -27
drivers/irqchip/irq-ls-scfg-msi.c
··· 14 14 #include <linux/iommu.h> 15 15 #include <linux/irq.h> 16 16 #include <linux/irqchip/chained_irq.h> 17 + #include <linux/irqchip/irq-msi-lib.h> 17 18 #include <linux/irqdomain.h> 18 19 #include <linux/of_irq.h> 19 20 #include <linux/of_pci.h> ··· 48 47 spinlock_t lock; 49 48 struct platform_device *pdev; 50 49 struct irq_domain *parent; 51 - struct irq_domain *msi_domain; 52 50 void __iomem *regs; 53 51 phys_addr_t msiir_addr; 54 52 struct ls_scfg_msi_cfg *cfg; ··· 57 57 unsigned long *used; 58 58 }; 59 59 60 - static struct irq_chip ls_scfg_msi_irq_chip = { 61 - .name = "MSI", 62 - .irq_mask = pci_msi_mask_irq, 63 - .irq_unmask = pci_msi_unmask_irq, 64 - }; 60 + #define MPIC_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 61 + MSI_FLAG_USE_DEF_CHIP_OPS) 62 + #define MPIC_MSI_FLAGS_SUPPORTED (MSI_FLAG_PCI_MSIX | \ 63 + MSI_GENERIC_FLAGS_MASK) 65 64 66 - static struct msi_domain_info ls_scfg_msi_domain_info = { 67 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | 68 - MSI_FLAG_USE_DEF_CHIP_OPS | 69 - MSI_FLAG_PCI_MSIX), 70 - .chip = &ls_scfg_msi_irq_chip, 65 + static const struct msi_parent_ops ls_scfg_msi_parent_ops = { 66 + .required_flags = MPIC_MSI_FLAGS_REQUIRED, 67 + .supported_flags = MPIC_MSI_FLAGS_SUPPORTED, 68 + .bus_select_token = DOMAIN_BUS_NEXUS, 69 + .bus_select_mask = MATCH_PCI_MSI, 70 + .prefix = "MSI-", 71 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 71 72 }; 72 73 73 74 static int msi_affinity_flag = 1; ··· 186 185 } 187 186 188 187 static const struct irq_domain_ops ls_scfg_msi_domain_ops = { 188 + .select = msi_lib_irq_domain_select, 189 189 .alloc = ls_scfg_msi_domain_irq_alloc, 190 190 .free = ls_scfg_msi_domain_irq_free, 191 191 }; ··· 216 214 217 215 static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data) 218 216 { 219 - /* Initialize MSI domain parent */ 220 - msi_data->parent = irq_domain_create_linear(NULL, 221 - msi_data->irqs_num, 222 - &ls_scfg_msi_domain_ops, 223 - msi_data); 224 - if (!msi_data->parent) { 225 - dev_err(&msi_data->pdev->dev, "failed to create IRQ domain\n"); 226 - return -ENOMEM; 227 - } 217 + struct irq_domain_info info = { 218 + .fwnode = of_fwnode_handle(msi_data->pdev->dev.of_node), 219 + .ops = &ls_scfg_msi_domain_ops, 220 + .host_data = msi_data, 221 + .size = msi_data->irqs_num, 222 + }; 228 223 229 - msi_data->msi_domain = pci_msi_create_irq_domain( 230 - of_fwnode_handle(msi_data->pdev->dev.of_node), 231 - &ls_scfg_msi_domain_info, 232 - msi_data->parent); 233 - if (!msi_data->msi_domain) { 224 + msi_data->parent = msi_create_parent_irq_domain(&info, &ls_scfg_msi_parent_ops); 225 + if (!msi_data->parent) { 234 226 dev_err(&msi_data->pdev->dev, "failed to create MSI domain\n"); 235 - irq_domain_remove(msi_data->parent); 236 227 return -ENOMEM; 237 228 } 238 229 ··· 400 405 for (i = 0; i < msi_data->msir_num; i++) 401 406 ls_scfg_msi_teardown_hwirq(&msi_data->msir[i]); 402 407 403 - irq_domain_remove(msi_data->msi_domain); 404 408 irq_domain_remove(msi_data->parent); 405 409 406 410 platform_set_drvdata(pdev, NULL);
+6 -2
drivers/irqchip/irq-mips-gic.c
··· 375 375 /* 376 376 * The GIC specifies that we can only route an interrupt to one VP(E), 377 377 * ie. CPU in Linux parlance, at a time. Therefore we always route to 378 - * the first online CPU in the mask. 378 + * the first forced or online CPU in the mask. 379 379 */ 380 - cpu = cpumask_first_and(cpumask, cpu_online_mask); 380 + if (force) 381 + cpu = cpumask_first(cpumask); 382 + else 383 + cpu = cpumask_first_and(cpumask, cpu_online_mask); 384 + 381 385 if (cpu >= NR_CPUS) 382 386 return -EINVAL; 383 387
+1 -1
drivers/irqchip/irq-mvebu-pic.c
··· 150 150 return -EINVAL; 151 151 } 152 152 153 - pic->domain = irq_domain_create_linear(of_fwnode_handle(node), PIC_MAX_IRQS, 153 + pic->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), PIC_MAX_IRQS, 154 154 &mvebu_pic_domain_ops, pic); 155 155 if (!pic->domain) { 156 156 dev_err(&pdev->dev, "Failed to allocate irq domain\n");
+1 -1
drivers/irqchip/irq-pruss-intc.c
··· 555 555 556 556 mutex_init(&intc->lock); 557 557 558 - intc->domain = irq_domain_create_linear(of_fwnode_handle(dev->of_node), max_system_events, 558 + intc->domain = irq_domain_create_linear(dev_fwnode(dev), max_system_events, 559 559 &pruss_intc_irq_domain_ops, intc); 560 560 if (!intc->domain) 561 561 return -ENOMEM;
+5 -7
drivers/irqchip/irq-renesas-intc-irqpin.c
··· 513 513 irq_chip->irq_set_wake = intc_irqpin_irq_set_wake; 514 514 irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND; 515 515 516 - p->irq_domain = irq_domain_create_simple(of_fwnode_handle(dev->of_node), 517 - nirqs, 0, 518 - &intc_irqpin_irq_domain_ops, 519 - p); 516 + p->irq_domain = irq_domain_create_simple(dev_fwnode(dev), nirqs, 0, 517 + &intc_irqpin_irq_domain_ops, p); 520 518 if (!p->irq_domain) { 521 519 ret = -ENXIO; 522 520 dev_err(dev, "cannot initialize irq domain\n"); ··· 570 572 pm_runtime_disable(&pdev->dev); 571 573 } 572 574 573 - static int __maybe_unused intc_irqpin_suspend(struct device *dev) 575 + static int intc_irqpin_suspend(struct device *dev) 574 576 { 575 577 struct intc_irqpin_priv *p = dev_get_drvdata(dev); 576 578 ··· 580 582 return 0; 581 583 } 582 584 583 - static SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL); 585 + static DEFINE_SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL); 584 586 585 587 static struct platform_driver intc_irqpin_device_driver = { 586 588 .probe = intc_irqpin_probe, ··· 588 590 .driver = { 589 591 .name = "renesas_intc_irqpin", 590 592 .of_match_table = intc_irqpin_dt_ids, 591 - .pm = &intc_irqpin_pm_ops, 593 + .pm = pm_sleep_ptr(&intc_irqpin_pm_ops), 592 594 } 593 595 }; 594 596
+4 -4
drivers/irqchip/irq-renesas-irqc.c
··· 168 168 169 169 p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ 170 170 171 - p->irq_domain = irq_domain_create_linear(of_fwnode_handle(dev->of_node), p->number_of_irqs, 171 + p->irq_domain = irq_domain_create_linear(dev_fwnode(dev), p->number_of_irqs, 172 172 &irq_generic_chip_ops, p); 173 173 if (!p->irq_domain) { 174 174 ret = -ENXIO; ··· 227 227 pm_runtime_disable(&pdev->dev); 228 228 } 229 229 230 - static int __maybe_unused irqc_suspend(struct device *dev) 230 + static int irqc_suspend(struct device *dev) 231 231 { 232 232 struct irqc_priv *p = dev_get_drvdata(dev); 233 233 ··· 237 237 return 0; 238 238 } 239 239 240 - static SIMPLE_DEV_PM_OPS(irqc_pm_ops, irqc_suspend, NULL); 240 + static DEFINE_SIMPLE_DEV_PM_OPS(irqc_pm_ops, irqc_suspend, NULL); 241 241 242 242 static const struct of_device_id irqc_dt_ids[] = { 243 243 { .compatible = "renesas,irqc", }, ··· 251 251 .driver = { 252 252 .name = "renesas_irqc", 253 253 .of_match_table = irqc_dt_ids, 254 - .pm = &irqc_pm_ops, 254 + .pm = pm_sleep_ptr(&irqc_pm_ops), 255 255 } 256 256 }; 257 257
+2 -3
drivers/irqchip/irq-renesas-rza1.c
··· 231 231 priv->chip.irq_set_type = rza1_irqc_set_type; 232 232 priv->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE; 233 233 234 - priv->irq_domain = irq_domain_create_hierarchy(parent, 0, IRQC_NUM_IRQ, 235 - of_fwnode_handle(np), &rza1_irqc_domain_ops, 236 - priv); 234 + priv->irq_domain = irq_domain_create_hierarchy(parent, 0, IRQC_NUM_IRQ, dev_fwnode(dev), 235 + &rza1_irqc_domain_ops, priv); 237 236 if (!priv->irq_domain) { 238 237 dev_err(dev, "cannot initialize irq domain\n"); 239 238 ret = -ENOMEM;
+2 -3
drivers/irqchip/irq-renesas-rzg2l.c
··· 574 574 575 575 raw_spin_lock_init(&rzg2l_irqc_data->lock); 576 576 577 - irq_domain = irq_domain_create_hierarchy(parent_domain, 0, IRQC_NUM_IRQ, 578 - of_fwnode_handle(node), &rzg2l_irqc_domain_ops, 579 - rzg2l_irqc_data); 577 + irq_domain = irq_domain_create_hierarchy(parent_domain, 0, IRQC_NUM_IRQ, dev_fwnode(dev), 578 + &rzg2l_irqc_domain_ops, rzg2l_irqc_data); 580 579 if (!irq_domain) { 581 580 pm_runtime_put(dev); 582 581 return dev_err_probe(dev, -ENOMEM, "failed to add irq domain\n");
+4 -5
drivers/irqchip/irq-renesas-rzv2h.c
··· 11 11 12 12 #include <linux/bitfield.h> 13 13 #include <linux/cleanup.h> 14 - #include <linux/clk.h> 15 14 #include <linux/err.h> 16 15 #include <linux/io.h> 17 16 #include <linux/irqchip.h> 18 17 #include <linux/irqchip/irq-renesas-rzv2h.h> 19 18 #include <linux/irqdomain.h> 20 - #include <linux/of_address.h> 21 19 #include <linux/of_platform.h> 22 20 #include <linux/pm_runtime.h> 23 21 #include <linux/reset.h> 24 22 #include <linux/spinlock.h> 25 - #include <linux/syscore_ops.h> 26 23 27 24 /* DT "interrupts" indexes */ 28 25 #define ICU_IRQ_START 1 ··· 424 427 .irq_retrigger = irq_chip_retrigger_hierarchy, 425 428 .irq_set_type = rzv2h_icu_set_type, 426 429 .irq_set_affinity = irq_chip_set_affinity_parent, 427 - .flags = IRQCHIP_SET_TYPE_MASKED, 430 + .flags = IRQCHIP_MASK_ON_SUSPEND | 431 + IRQCHIP_SET_TYPE_MASKED | 432 + IRQCHIP_SKIP_SET_WAKE, 428 433 }; 429 434 430 435 static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, ··· 557 558 raw_spin_lock_init(&rzv2h_icu_data->lock); 558 559 559 560 irq_domain = irq_domain_create_hierarchy(parent_domain, 0, ICU_NUM_IRQ, 560 - of_fwnode_handle(node), &rzv2h_icu_domain_ops, 561 + dev_fwnode(&pdev->dev), &rzv2h_icu_domain_ops, 561 562 rzv2h_icu_data); 562 563 if (!irq_domain) { 563 564 dev_err(&pdev->dev, "failed to add irq domain\n");
+1 -15
drivers/irqchip/irq-riscv-aplic-direct.c
··· 219 219 return 0; 220 220 } 221 221 222 - static int aplic_direct_get_hart_index(struct device *dev, u32 logical_index, 223 - u32 *hart_index) 224 - { 225 - const char *prop_hart_index = "riscv,hart-indexes"; 226 - struct device_node *np = to_of_node(dev->fwnode); 227 - 228 - if (!np || !of_property_present(np, prop_hart_index)) { 229 - *hart_index = logical_index; 230 - return 0; 231 - } 232 - 233 - return of_property_read_u32_index(np, prop_hart_index, logical_index, hart_index); 234 - } 235 - 236 222 int aplic_direct_setup(struct device *dev, void __iomem *regs) 237 223 { 238 224 int i, j, rc, cpu, current_cpu, setup_count = 0; ··· 265 279 cpumask_set_cpu(cpu, &direct->lmask); 266 280 267 281 idc = per_cpu_ptr(&aplic_idcs, cpu); 268 - rc = aplic_direct_get_hart_index(dev, i, &idc->hart_index); 282 + rc = riscv_get_hart_index(dev->fwnode, i, &idc->hart_index); 269 283 if (rc) { 270 284 dev_warn(dev, "hart index not found for IDC%d\n", i); 271 285 continue;
+19 -1
drivers/irqchip/irq-riscv-imsic-early.c
··· 8 8 #include <linux/acpi.h> 9 9 #include <linux/cpu.h> 10 10 #include <linux/interrupt.h> 11 + #include <linux/init.h> 11 12 #include <linux/io.h> 12 13 #include <linux/irq.h> 13 14 #include <linux/irqchip.h> ··· 22 21 #include "irq-riscv-imsic-state.h" 23 22 24 23 static int imsic_parent_irq; 24 + bool imsic_noipi __ro_after_init; 25 + 26 + static int __init imsic_noipi_cfg(char *buf) 27 + { 28 + imsic_noipi = true; 29 + return 0; 30 + } 31 + early_param("irqchip.riscv_imsic_noipi", imsic_noipi_cfg); 25 32 26 33 #ifdef CONFIG_SMP 27 34 static void imsic_ipi_send(unsigned int cpu) ··· 41 32 42 33 static void imsic_ipi_starting_cpu(void) 43 34 { 35 + if (imsic_noipi) 36 + return; 37 + 44 38 /* Enable IPIs for current CPU. */ 45 39 __imsic_id_set_enable(IMSIC_IPI_ID); 46 40 } 47 41 48 42 static void imsic_ipi_dying_cpu(void) 49 43 { 44 + if (imsic_noipi) 45 + return; 46 + 50 47 /* Disable IPIs for current CPU. */ 51 48 __imsic_id_clear_enable(IMSIC_IPI_ID); 52 49 } ··· 60 45 static int __init imsic_ipi_domain_init(void) 61 46 { 62 47 int virq; 48 + 49 + if (imsic_noipi) 50 + return 0; 63 51 64 52 /* Create IMSIC IPI multiplexing */ 65 53 virq = ipi_mux_create(IMSIC_NR_IPI, imsic_ipi_send); ··· 106 88 while ((local_id = csr_swap(CSR_TOPEI, 0))) { 107 89 local_id >>= TOPEI_ID_SHIFT; 108 90 109 - if (local_id == IMSIC_IPI_ID) { 91 + if (!imsic_noipi && local_id == IMSIC_IPI_ID) { 110 92 if (IS_ENABLED(CONFIG_SMP)) 111 93 ipi_mux_process(); 112 94 continue;
+6 -6
drivers/irqchip/irq-riscv-imsic-platform.c
··· 307 307 308 308 int imsic_irqdomain_init(void) 309 309 { 310 + struct irq_domain_info info = { 311 + .fwnode = imsic->fwnode, 312 + .ops = &imsic_base_domain_ops, 313 + .host_data = imsic, 314 + }; 310 315 struct imsic_global_config *global; 311 316 312 317 if (!imsic || !imsic->fwnode) { ··· 325 320 } 326 321 327 322 /* Create Base IRQ domain */ 328 - imsic->base_domain = irq_domain_create_tree(imsic->fwnode, 329 - &imsic_base_domain_ops, imsic); 323 + imsic->base_domain = msi_create_parent_irq_domain(&info, &imsic_msi_parent_ops); 330 324 if (!imsic->base_domain) { 331 325 pr_err("%pfwP: failed to create IMSIC base domain\n", imsic->fwnode); 332 326 return -ENOMEM; 333 327 } 334 - imsic->base_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 335 - imsic->base_domain->msi_parent_ops = &imsic_msi_parent_ops; 336 - 337 - irq_domain_update_bus_token(imsic->base_domain, DOMAIN_BUS_NEXUS); 338 328 339 329 global = &imsic->global; 340 330 pr_info("%pfwP: hart-index-bits: %d, guest-index-bits: %d\n",
+4 -3
drivers/irqchip/irq-riscv-imsic-state.c
··· 134 134 lockdep_assert_held(&lpriv->lock); 135 135 136 136 for_each_set_bit(i, lpriv->dirty_bitmap, imsic->global.nr_ids + 1) { 137 - if (!i || i == IMSIC_IPI_ID) 137 + if (!i || (!imsic_noipi && i == IMSIC_IPI_ID)) 138 138 goto skip; 139 139 vec = &lpriv->vectors[i]; 140 140 ··· 419 419 seq_printf(m, "%*starget_cpu : %5u\n", ind, "", vec->cpu); 420 420 seq_printf(m, "%*starget_local_id : %5u\n", ind, "", vec->local_id); 421 421 seq_printf(m, "%*sis_reserved : %5u\n", ind, "", 422 - (vec->local_id <= IMSIC_IPI_ID) ? 1 : 0); 422 + (!imsic_noipi && vec->local_id <= IMSIC_IPI_ID) ? 1 : 0); 423 423 seq_printf(m, "%*sis_enabled : %5u\n", ind, "", is_enabled ? 1 : 0); 424 424 seq_printf(m, "%*sis_move_pending : %5u\n", ind, "", mvec ? 1 : 0); 425 425 if (mvec) { ··· 583 583 irq_matrix_assign_system(imsic->matrix, 0, false); 584 584 585 585 /* Reserve IPI ID because it is special and used internally */ 586 - irq_matrix_assign_system(imsic->matrix, IMSIC_IPI_ID, false); 586 + if (!imsic_noipi) 587 + irq_matrix_assign_system(imsic->matrix, IMSIC_IPI_ID, false); 587 588 588 589 return 0; 589 590 }
+1
drivers/irqchip/irq-riscv-imsic-state.h
··· 61 61 struct irq_domain *base_domain; 62 62 }; 63 63 64 + extern bool imsic_noipi; 64 65 extern struct imsic_priv *imsic; 65 66 66 67 void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val);
+8 -10
drivers/irqchip/irq-sg2042-msi.c
··· 219 219 static int sg204x_msi_init_domains(struct sg204x_msi_chipdata *data, 220 220 struct irq_domain *plic_domain, struct device *dev) 221 221 { 222 - struct fwnode_handle *fwnode = dev_fwnode(dev); 223 - struct irq_domain *middle_domain; 222 + struct irq_domain_info info = { 223 + .ops = &sg204x_msi_middle_domain_ops, 224 + .parent = plic_domain, 225 + .size = data->num_irqs, 226 + .fwnode = dev_fwnode(dev), 227 + .host_data = data, 228 + }; 224 229 225 - middle_domain = irq_domain_create_hierarchy(plic_domain, 0, data->num_irqs, fwnode, 226 - &sg204x_msi_middle_domain_ops, data); 227 - if (!middle_domain) { 230 + if (!msi_create_parent_irq_domain(&info, data->chip_info->parent_ops)) { 228 231 pr_err("Failed to create the MSI middle domain\n"); 229 232 return -ENOMEM; 230 233 } 231 - 232 - irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); 233 - 234 - middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 235 - middle_domain->msi_parent_ops = data->chip_info->parent_ops; 236 234 return 0; 237 235 } 238 236
+1 -3
drivers/irqchip/irq-stm32mp-exti.c
··· 683 683 } 684 684 685 685 domain = irq_domain_create_hierarchy(parent_domain, 0, drv_data->bank_nr * IRQS_PER_BANK, 686 - of_fwnode_handle(np), &stm32mp_exti_domain_ops, 687 - host_data); 688 - 686 + dev_fwnode(dev), &stm32mp_exti_domain_ops, host_data); 689 687 if (!domain) { 690 688 dev_err(dev, "Could not register exti domain\n"); 691 689 return -ENOMEM;
+73 -41
drivers/irqchip/irq-thead-c900-aclint-sswi.c drivers/irqchip/irq-aclint-sswi.c
··· 3 3 * Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com> 4 4 */ 5 5 6 - #define pr_fmt(fmt) "thead-c900-aclint-sswi: " fmt 6 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 + 7 8 #include <linux/cpu.h> 8 9 #include <linux/interrupt.h> 9 - #include <linux/io.h> 10 - #include <linux/irq.h> 11 10 #include <linux/irqchip.h> 12 11 #include <linux/irqchip/chained_irq.h> 13 - #include <linux/module.h> 14 - #include <linux/of.h> 15 12 #include <linux/of_address.h> 16 - #include <linux/of_irq.h> 17 - #include <linux/pci.h> 18 13 #include <linux/spinlock.h> 19 14 #include <linux/smp.h> 20 15 #include <linux/string_choices.h> 21 16 #include <asm/sbi.h> 22 17 #include <asm/vendorid_list.h> 23 18 24 - #define THEAD_ACLINT_xSWI_REGISTER_SIZE 4 25 - 26 - #define THEAD_C9XX_CSR_SXSTATUS 0x5c0 27 - #define THEAD_C9XX_SXSTATUS_CLINTEE BIT(17) 28 - 29 19 static int sswi_ipi_virq __ro_after_init; 30 20 static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs); 31 21 32 - static void thead_aclint_sswi_ipi_send(unsigned int cpu) 22 + static void aclint_sswi_ipi_send(unsigned int cpu) 33 23 { 34 24 writel(0x1, per_cpu(sswi_cpu_regs, cpu)); 35 25 } 36 26 37 - static void thead_aclint_sswi_ipi_clear(void) 27 + static void aclint_sswi_ipi_clear(void) 38 28 { 39 29 writel_relaxed(0x0, this_cpu_read(sswi_cpu_regs)); 40 30 } 41 31 42 - static void thead_aclint_sswi_ipi_handle(struct irq_desc *desc) 32 + static void aclint_sswi_ipi_handle(struct irq_desc *desc) 43 33 { 44 34 struct irq_chip *chip = irq_desc_get_chip(desc); 45 35 46 36 chained_irq_enter(chip, desc); 47 37 48 38 csr_clear(CSR_IP, IE_SIE); 49 - thead_aclint_sswi_ipi_clear(); 39 + aclint_sswi_ipi_clear(); 50 40 51 41 ipi_mux_process(); 52 42 53 43 chained_irq_exit(chip, desc); 54 44 } 55 45 56 - static int thead_aclint_sswi_starting_cpu(unsigned int cpu) 46 + static int aclint_sswi_starting_cpu(unsigned int cpu) 57 47 { 58 48 enable_percpu_irq(sswi_ipi_virq, irq_get_trigger_type(sswi_ipi_virq)); 59 49 60 50 return 0; 61 51 } 62 52 63 - static int thead_aclint_sswi_dying_cpu(unsigned int cpu) 53 + static int aclint_sswi_dying_cpu(unsigned int cpu) 64 54 { 65 - thead_aclint_sswi_ipi_clear(); 55 + aclint_sswi_ipi_clear(); 66 56 67 57 disable_percpu_irq(sswi_ipi_virq); 68 58 69 59 return 0; 70 60 } 71 61 72 - static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode, 73 - void __iomem *reg) 62 + static int __init aclint_sswi_parse_irq(struct fwnode_handle *fwnode, void __iomem *reg) 74 63 { 75 - struct of_phandle_args parent; 76 - unsigned long hartid; 77 - u32 contexts, i; 78 - int rc, cpu; 64 + u32 contexts = of_irq_count(to_of_node(fwnode)); 79 65 80 - contexts = of_irq_count(to_of_node(fwnode)); 81 66 if (!(contexts)) { 82 67 pr_err("%pfwP: no ACLINT SSWI context available\n", fwnode); 83 68 return -EINVAL; 84 69 } 85 70 86 - for (i = 0; i < contexts; i++) { 71 + for (u32 i = 0; i < contexts; i++) { 72 + struct of_phandle_args parent; 73 + unsigned long hartid; 74 + u32 hart_index; 75 + int rc, cpu; 76 + 87 77 rc = of_irq_parse_one(to_of_node(fwnode), i, &parent); 88 78 if (rc) 89 79 return rc; ··· 87 97 88 98 cpu = riscv_hartid_to_cpuid(hartid); 89 99 90 - per_cpu(sswi_cpu_regs, cpu) = reg + i * THEAD_ACLINT_xSWI_REGISTER_SIZE; 100 + rc = riscv_get_hart_index(fwnode, i, &hart_index); 101 + if (rc) { 102 + pr_warn("%pfwP: hart index [%d] not found\n", fwnode, i); 103 + return -EINVAL; 104 + } 105 + per_cpu(sswi_cpu_regs, cpu) = reg + hart_index * 4; 91 106 } 92 107 93 108 pr_info("%pfwP: register %u CPU%s\n", fwnode, contexts, str_plural(contexts)); ··· 100 105 return 0; 101 106 } 102 107 103 - static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode) 108 + static int __init aclint_sswi_probe(struct fwnode_handle *fwnode) 104 109 { 105 110 struct irq_domain *domain; 106 111 void __iomem *reg; 107 112 int virq, rc; 108 - 109 - /* If it is T-HEAD CPU, check whether SSWI is enabled */ 110 - if (riscv_cached_mvendorid(0) == THEAD_VENDOR_ID && 111 - !(csr_read(THEAD_C9XX_CSR_SXSTATUS) & THEAD_C9XX_SXSTATUS_CLINTEE)) 112 - return -ENOTSUPP; 113 113 114 114 if (!is_of_node(fwnode)) 115 115 return -EINVAL; ··· 114 124 return -ENOMEM; 115 125 116 126 /* Parse SSWI setting */ 117 - rc = thead_aclint_sswi_parse_irq(fwnode, reg); 127 + rc = aclint_sswi_parse_irq(fwnode, reg); 118 128 if (rc < 0) 119 129 return rc; 120 130 ··· 136 146 } 137 147 138 148 /* Register SSWI irq and handler */ 139 - virq = ipi_mux_create(BITS_PER_BYTE, thead_aclint_sswi_ipi_send); 149 + virq = ipi_mux_create(BITS_PER_BYTE, aclint_sswi_ipi_send); 140 150 if (virq <= 0) { 141 151 pr_err("unable to create muxed IPIs\n"); 142 152 irq_dispose_mapping(sswi_ipi_virq); 143 153 return virq < 0 ? virq : -ENOMEM; 144 154 } 145 155 146 - irq_set_chained_handler(sswi_ipi_virq, thead_aclint_sswi_ipi_handle); 156 + irq_set_chained_handler(sswi_ipi_virq, aclint_sswi_ipi_handle); 147 157 148 - cpuhp_setup_state(CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING, 149 - "irqchip/thead-aclint-sswi:starting", 150 - thead_aclint_sswi_starting_cpu, 151 - thead_aclint_sswi_dying_cpu); 158 + cpuhp_setup_state(CPUHP_AP_IRQ_ACLINT_SSWI_STARTING, 159 + "irqchip/aclint-sswi:starting", 160 + aclint_sswi_starting_cpu, 161 + aclint_sswi_dying_cpu); 152 162 153 163 riscv_ipi_set_virq_range(virq, BITS_PER_BYTE); 164 + 165 + return 0; 166 + } 167 + 168 + /* generic/MIPS variant */ 169 + static int __init generic_aclint_sswi_probe(struct fwnode_handle *fwnode) 170 + { 171 + int rc; 172 + 173 + rc = aclint_sswi_probe(fwnode); 174 + if (rc) 175 + return rc; 176 + 177 + /* Announce that SSWI is providing IPIs */ 178 + pr_info("providing IPIs using ACLINT SSWI\n"); 179 + 180 + return 0; 181 + } 182 + 183 + static int __init generic_aclint_sswi_early_probe(struct device_node *node, 184 + struct device_node *parent) 185 + { 186 + return generic_aclint_sswi_probe(&node->fwnode); 187 + } 188 + IRQCHIP_DECLARE(generic_aclint_sswi, "mips,p8700-aclint-sswi", generic_aclint_sswi_early_probe); 189 + 190 + /* THEAD variant */ 191 + #define THEAD_C9XX_CSR_SXSTATUS 0x5c0 192 + #define THEAD_C9XX_SXSTATUS_CLINTEE BIT(17) 193 + 194 + static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode) 195 + { 196 + int rc; 197 + 198 + /* If it is T-HEAD CPU, check whether SSWI is enabled */ 199 + if (riscv_cached_mvendorid(0) == THEAD_VENDOR_ID && 200 + !(csr_read(THEAD_C9XX_CSR_SXSTATUS) & THEAD_C9XX_SXSTATUS_CLINTEE)) 201 + return -ENOTSUPP; 202 + 203 + rc = aclint_sswi_probe(fwnode); 204 + if (rc) 205 + return rc; 154 206 155 207 /* Announce that SSWI is providing IPIs */ 156 208 pr_info("providing IPIs using THEAD ACLINT SSWI\n");
+1 -2
drivers/irqchip/irq-ti-sci-inta.c
··· 701 701 if (ret) 702 702 return ret; 703 703 704 - domain = irq_domain_create_linear(of_fwnode_handle(dev_of_node(dev)), 705 - ti_sci_get_num_resources(inta->vint), 704 + domain = irq_domain_create_linear(dev_fwnode(dev), ti_sci_get_num_resources(inta->vint), 706 705 &ti_sci_inta_irq_domain_ops, inta); 707 706 if (!domain) { 708 707 dev_err(dev, "Failed to allocate IRQ domain\n");
+1 -2
drivers/irqchip/irq-ti-sci-intr.c
··· 274 274 return PTR_ERR(intr->out_irqs); 275 275 } 276 276 277 - domain = irq_domain_create_hierarchy(parent_domain, 0, 0, 278 - of_fwnode_handle(dev_of_node(dev)), 277 + domain = irq_domain_create_hierarchy(parent_domain, 0, 0, dev_fwnode(dev), 279 278 &ti_sci_intr_irq_domain_ops, intr); 280 279 if (!domain) { 281 280 dev_err(dev, "Failed to allocate IRQ domain\n");
+1 -1
drivers/irqchip/irq-ts4800.c
··· 125 125 return -EINVAL; 126 126 } 127 127 128 - data->domain = irq_domain_create_linear(of_fwnode_handle(node), 8, &ts4800_ic_ops, data); 128 + data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), 8, &ts4800_ic_ops, data); 129 129 if (!data->domain) { 130 130 dev_err(&pdev->dev, "cannot add IRQ domain\n"); 131 131 return -ENOMEM;
+1 -1
include/linux/cpuhotplug.h
··· 145 145 CPUHP_AP_IRQ_EIOINTC_STARTING, 146 146 CPUHP_AP_IRQ_AVECINTC_STARTING, 147 147 CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, 148 - CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING, 148 + CPUHP_AP_IRQ_ACLINT_SSWI_STARTING, 149 149 CPUHP_AP_IRQ_RISCV_IMSIC_STARTING, 150 150 CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING, 151 151 CPUHP_AP_ARM_MVEBU_COHERENCY,
+2
include/linux/irqdomain.h
··· 279 279 * domains are added using same fwnode 280 280 * @ops: Domain operation callbacks 281 281 * @host_data: Controller private data pointer 282 + * @dev: Device which creates the domain 282 283 * @dgc_info: Geneneric chip information structure pointer used to 283 284 * create generic chips for the domain if not NULL. 284 285 * @init: Function called when the domain is created. ··· 299 298 const char *name_suffix; 300 299 const struct irq_domain_ops *ops; 301 300 void *host_data; 301 + struct device *dev; 302 302 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 303 303 /** 304 304 * @parent: Pointer to the parent irq domain used in a hierarchy domain
+2
include/linux/msi.h
··· 488 488 * gets initialized to the maximum software index limit 489 489 * by the domain creation code. 490 490 * @ops: The callback data structure 491 + * @dev: Device which creates the domain 491 492 * @chip: Optional: associated interrupt chip 492 493 * @chip_data: Optional: associated interrupt chip data 493 494 * @handler: Optional: associated interrupt flow handler ··· 502 501 enum irq_domain_bus_token bus_token; 503 502 unsigned int hwsize; 504 503 struct msi_domain_ops *ops; 504 + struct device *dev; 505 505 struct irq_chip *chip; 506 506 void *chip_data; 507 507 irq_flow_handler_t handler;
+1
kernel/irq/irqdomain.c
··· 317 317 318 318 domain->flags |= info->domain_flags; 319 319 domain->exit = info->exit; 320 + domain->dev = info->dev; 320 321 321 322 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 322 323 if (info->parent) {
+2 -1
kernel/irq/msi.c
··· 889 889 890 890 if (domain) { 891 891 irq_domain_update_bus_token(domain, info->bus_token); 892 + domain->dev = info->dev; 892 893 if (info->flags & MSI_FLAG_PARENT_PM_DEV) 893 894 domain->pm_dev = parent->pm_dev; 894 895 } ··· 1052 1051 bundle->info.data = domain_data; 1053 1052 bundle->info.chip_data = chip_data; 1054 1053 bundle->info.alloc_data = &bundle->alloc_info; 1054 + bundle->info.dev = dev; 1055 1055 1056 1056 pops = parent->msi_parent_ops; 1057 1057 snprintf(bundle->name, sizeof(bundle->name), "%s%s-%s", ··· 1091 1089 if (!domain) 1092 1090 return false; 1093 1091 1094 - domain->dev = dev; 1095 1092 dev->msi.data->__domains[domid].domain = domain; 1096 1093 1097 1094 if (msi_domain_prepare_irqs(domain, dev, hwsize, &bundle->alloc_info)) {