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

Merge tag 'irq-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
"Updates for the interrupt core and driver subsystem:

The bulk is the rework of the MSI subsystem to support per device MSI
interrupt domains. This solves conceptual problems of the current
PCI/MSI design which are in the way of providing support for
PCI/MSI[-X] and the upcoming PCI/IMS mechanism on the same device.

IMS (Interrupt Message Store] is a new specification which allows
device manufactures to provide implementation defined storage for MSI
messages (as opposed to PCI/MSI and PCI/MSI-X that has a specified
message store which is uniform accross all devices). The PCI/MSI[-X]
uniformity allowed us to get away with "global" PCI/MSI domains.

IMS not only allows to overcome the size limitations of the MSI-X
table, but also gives the device manufacturer the freedom to store the
message in arbitrary places, even in host memory which is shared with
the device.

There have been several attempts to glue this into the current MSI
code, but after lengthy discussions it turned out that there is a
fundamental design problem in the current PCI/MSI-X implementation.
This needs some historical background.

When PCI/MSI[-X] support was added around 2003, interrupt management
was completely different from what we have today in the actively
developed architectures. Interrupt management was completely
architecture specific and while there were attempts to create common
infrastructure the commonalities were rudimentary and just providing
shared data structures and interfaces so that drivers could be written
in an architecture agnostic way.

The initial PCI/MSI[-X] support obviously plugged into this model
which resulted in some basic shared infrastructure in the PCI core
code for setting up MSI descriptors, which are a pure software
construct for holding data relevant for a particular MSI interrupt,
but the actual association to Linux interrupts was completely
architecture specific. This model is still supported today to keep
museum architectures and notorious stragglers alive.

In 2013 Intel tried to add support for hot-pluggable IO/APICs to the
kernel, which was creating yet another architecture specific mechanism
and resulted in an unholy mess on top of the existing horrors of x86
interrupt handling. The x86 interrupt management code was already an
incomprehensible maze of indirections between the CPU vector
management, interrupt remapping and the actual IO/APIC and PCI/MSI[-X]
implementation.

At roughly the same time ARM struggled with the ever growing SoC
specific extensions which were glued on top of the architected GIC
interrupt controller.

This resulted in a fundamental redesign of interrupt management and
provided the today prevailing concept of hierarchical interrupt
domains. This allowed to disentangle the interactions between x86
vector domain and interrupt remapping and also allowed ARM to handle
the zoo of SoC specific interrupt components in a sane way.

The concept of hierarchical interrupt domains aims to encapsulate the
functionality of particular IP blocks which are involved in interrupt
delivery so that they become extensible and pluggable. The X86
encapsulation looks like this:

|--- device 1
[Vector]---[Remapping]---[PCI/MSI]--|...
|--- device N

where the remapping domain is an optional component and in case that
it is not available the PCI/MSI[-X] domains have the vector domain as
their parent. This reduced the required interaction between the
domains pretty much to the initialization phase where it is obviously
required to establish the proper parent relation ship in the
components of the hierarchy.

While in most cases the model is strictly representing the chain of IP
blocks and abstracting them so they can be plugged together to form a
hierarchy, the design stopped short on PCI/MSI[-X]. Looking at the
hardware it's clear that the actual PCI/MSI[-X] interrupt controller
is not a global entity, but strict a per PCI device entity.

Here we took a short cut on the hierarchical model and went for the
easy solution of providing "global" PCI/MSI domains which was possible
because the PCI/MSI[-X] handling is uniform across the devices. This
also allowed to keep the existing PCI/MSI[-X] infrastructure mostly
unchanged which in turn made it simple to keep the existing
architecture specific management alive.

A similar problem was created in the ARM world with support for IP
block specific message storage. Instead of going all the way to stack
a IP block specific domain on top of the generic MSI domain this ended
in a construct which provides a "global" platform MSI domain which
allows overriding the irq_write_msi_msg() callback per allocation.

In course of the lengthy discussions we identified other abuse of the
MSI infrastructure in wireless drivers, NTB etc. where support for
implementation specific message storage was just mindlessly glued into
the existing infrastructure. Some of this just works by chance on
particular platforms but will fail in hard to diagnose ways when the
driver is used on platforms where the underlying MSI interrupt
management code does not expect the creative abuse.

Another shortcoming of today's PCI/MSI-X support is the inability to
allocate or free individual vectors after the initial enablement of
MSI-X. This results in an works by chance implementation of VFIO (PCI
pass-through) where interrupts on the host side are not set up upfront
to avoid resource exhaustion. They are expanded at run-time when the
guest actually tries to use them. The way how this is implemented is
that the host disables MSI-X and then re-enables it with a larger
number of vectors again. That works by chance because most device
drivers set up all interrupts before the device actually will utilize
them. But that's not universally true because some drivers allocate a
large enough number of vectors but do not utilize them until it's
actually required, e.g. for acceleration support. But at that point
other interrupts of the device might be in active use and the MSI-X
disable/enable dance can just result in losing interrupts and
therefore hard to diagnose subtle problems.

Last but not least the "global" PCI/MSI-X domain approach prevents to
utilize PCI/MSI[-X] and PCI/IMS on the same device due to the fact
that IMS is not longer providing a uniform storage and configuration
model.

The solution to this is to implement the missing step and switch from
global PCI/MSI domains to per device PCI/MSI domains. The resulting
hierarchy then looks like this:

|--- [PCI/MSI] device 1
[Vector]---[Remapping]---|...
|--- [PCI/MSI] device N

which in turn allows to provide support for multiple domains per
device:

|--- [PCI/MSI] device 1
|--- [PCI/IMS] device 1
[Vector]---[Remapping]---|...
|--- [PCI/MSI] device N
|--- [PCI/IMS] device N

This work converts the MSI and PCI/MSI core and the x86 interrupt
domains to the new model, provides new interfaces for post-enable
allocation/free of MSI-X interrupts and the base framework for
PCI/IMS. PCI/IMS has been verified with the work in progress IDXD
driver.

There is work in progress to convert ARM over which will replace the
platform MSI train-wreck. The cleanup of VFIO, NTB and other creative
"solutions" are in the works as well.

Drivers:

- Updates for the LoongArch interrupt chip drivers

- Support for MTK CIRQv2

- The usual small fixes and updates all over the place"

* tag 'irq-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (134 commits)
irqchip/ti-sci-inta: Fix kernel doc
irqchip/gic-v2m: Mark a few functions __init
irqchip/gic-v2m: Include arm-gic-common.h
irqchip/irq-mvebu-icu: Fix works by chance pointer assignment
iommu/amd: Enable PCI/IMS
iommu/vt-d: Enable PCI/IMS
x86/apic/msi: Enable PCI/IMS
PCI/MSI: Provide pci_ims_alloc/free_irq()
PCI/MSI: Provide IMS (Interrupt Message Store) support
genirq/msi: Provide constants for PCI/IMS support
x86/apic/msi: Enable MSI_FLAG_PCI_MSIX_ALLOC_DYN
PCI/MSI: Provide post-enable dynamic allocation interfaces for MSI-X
PCI/MSI: Provide prepare_desc() MSI domain op
PCI/MSI: Split MSI-X descriptor setup
genirq/msi: Provide MSI_FLAG_MSIX_ALLOC_DYN
genirq/msi: Provide msi_domain_alloc_irq_at()
genirq/msi: Provide msi_domain_ops:: Prepare_desc()
genirq/msi: Provide msi_desc:: Msi_data
genirq/msi: Provide struct msi_map
x86/apic/msi: Remove arch_create_remap_msi_irq_domain()
...

+3520 -1668
+10
Documentation/PCI/msi-howto.rst
··· 285 285 It is also worth checking the device driver to see whether it supports MSIs. 286 286 For example, it may contain calls to pci_alloc_irq_vectors() with the 287 287 PCI_IRQ_MSI or PCI_IRQ_MSIX flags. 288 + 289 + 290 + List of device drivers MSI(-X) APIs 291 + =================================== 292 + 293 + The PCI/MSI subystem has a dedicated C file for its exported device driver 294 + APIs — `drivers/pci/msi/api.c`. The following functions are exported: 295 + 296 + .. kernel-doc:: drivers/pci/msi/api.c 297 + :export:
+34
Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/loongarch,cpu-interrupt-controller.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: LoongArch CPU Interrupt Controller 8 + 9 + maintainers: 10 + - Liu Peibao <liupeibao@loongson.cn> 11 + 12 + properties: 13 + compatible: 14 + const: loongarch,cpu-interrupt-controller 15 + 16 + '#interrupt-cells': 17 + const: 1 18 + 19 + interrupt-controller: true 20 + 21 + additionalProperties: false 22 + 23 + required: 24 + - compatible 25 + - '#interrupt-cells' 26 + - interrupt-controller 27 + 28 + examples: 29 + - | 30 + interrupt-controller { 31 + compatible = "loongarch,cpu-interrupt-controller"; 32 + #interrupt-cells = <1>; 33 + interrupt-controller; 34 + };
-33
Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
··· 1 - * Mediatek 27xx cirq 2 - 3 - In Mediatek SOCs, the CIRQ is a low power interrupt controller designed to 4 - work outside MCUSYS which comprises with Cortex-Ax cores,CCI and GIC. 5 - The external interrupts (outside MCUSYS) will feed through CIRQ and connect 6 - to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive 7 - interrupts and generate a pulse signal to parent interrupt controller when 8 - flush command is executed. With CIRQ, MCUSYS can be completely turned off 9 - to improve the system power consumption without losing interrupts. 10 - 11 - Required properties: 12 - - compatible: should be one of 13 - - "mediatek,mt2701-cirq" for mt2701 CIRQ 14 - - "mediatek,mt8135-cirq" for mt8135 CIRQ 15 - - "mediatek,mt8173-cirq" for mt8173 CIRQ 16 - and "mediatek,cirq" as a fallback. 17 - - interrupt-controller : Identifies the node as an interrupt controller. 18 - - #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt. 19 - - reg: Physical base address of the cirq registers and length of memory 20 - mapped region. 21 - - mediatek,ext-irq-range: Identifies external irq number range in different 22 - SOCs. 23 - 24 - Example: 25 - cirq: interrupt-controller@10204000 { 26 - compatible = "mediatek,mt2701-cirq", 27 - "mediatek,mtk-cirq"; 28 - interrupt-controller; 29 - #interrupt-cells = <3>; 30 - interrupt-parent = <&sysirq>; 31 - reg = <0 0x10204000 0 0x400>; 32 - mediatek,ext-irq-start = <32 200>; 33 - };
+68
Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/mediatek,mtk-cirq.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek System Interrupt Controller 8 + 9 + maintainers: 10 + - Youlin Pei <youlin.pei@mediatek.com> 11 + 12 + description: 13 + In MediaTek SoCs, the CIRQ is a low power interrupt controller designed to 14 + work outside of MCUSYS which comprises with Cortex-Ax cores, CCI and GIC. 15 + The external interrupts (outside MCUSYS) will feed through CIRQ and connect 16 + to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive 17 + interrupts and generate a pulse signal to parent interrupt controller when 18 + flush command is executed. With CIRQ, MCUSYS can be completely turned off 19 + to improve the system power consumption without losing interrupts. 20 + 21 + 22 + properties: 23 + compatible: 24 + items: 25 + - enum: 26 + - mediatek,mt2701-cirq 27 + - mediatek,mt8135-cirq 28 + - mediatek,mt8173-cirq 29 + - mediatek,mt8192-cirq 30 + - const: mediatek,mtk-cirq 31 + 32 + reg: 33 + maxItems: 1 34 + 35 + '#interrupt-cells': 36 + const: 3 37 + 38 + interrupt-controller: true 39 + 40 + mediatek,ext-irq-range: 41 + $ref: /schemas/types.yaml#/definitions/uint32-array 42 + items: 43 + - description: First CIRQ interrupt 44 + - description: Last CIRQ interrupt 45 + description: 46 + Identifies the range of external interrupts in different SoCs 47 + 48 + required: 49 + - compatible 50 + - reg 51 + - '#interrupt-cells' 52 + - interrupt-controller 53 + - mediatek,ext-irq-range 54 + 55 + additionalProperties: false 56 + 57 + examples: 58 + - | 59 + #include <dt-bindings/interrupt-controller/irq.h> 60 + 61 + cirq: interrupt-controller@10204000 { 62 + compatible = "mediatek,mt2701-cirq", "mediatek,mtk-cirq"; 63 + reg = <0x10204000 0x400>; 64 + #interrupt-cells = <3>; 65 + interrupt-controller; 66 + interrupt-parent = <&sysirq>; 67 + mediatek,ext-irq-range = <32 200>; 68 + };
+1 -1
arch/loongarch/include/asm/irq.h
··· 93 93 int eiointc_acpi_init(struct irq_domain *parent, 94 94 struct acpi_madt_eio_pic *acpi_eiointc); 95 95 96 - struct irq_domain *htvec_acpi_init(struct irq_domain *parent, 96 + int htvec_acpi_init(struct irq_domain *parent, 97 97 struct acpi_madt_ht_pic *acpi_htvec); 98 98 int pch_lpc_acpi_init(struct irq_domain *parent, 99 99 struct acpi_madt_lpc_pic *acpi_pchlpc);
+2 -5
arch/powerpc/platforms/pseries/msi.c
··· 447 447 * RTAS can not disable one MSI at a time. It's all or nothing. Do it 448 448 * at the end after all IRQs have been freed. 449 449 */ 450 - static void pseries_msi_domain_free_irqs(struct irq_domain *domain, 451 - struct device *dev) 450 + static void pseries_msi_post_free(struct irq_domain *domain, struct device *dev) 452 451 { 453 452 if (WARN_ON_ONCE(!dev_is_pci(dev))) 454 453 return; 455 - 456 - __msi_domain_free_irqs(domain, dev); 457 454 458 455 rtas_disable_msi(to_pci_dev(dev)); 459 456 } ··· 458 461 static struct msi_domain_ops pseries_pci_msi_domain_ops = { 459 462 .msi_prepare = pseries_msi_ops_prepare, 460 463 .msi_free = pseries_msi_ops_msi_free, 461 - .domain_free_irqs = pseries_msi_domain_free_irqs, 464 + .msi_post_free = pseries_msi_post_free, 462 465 }; 463 466 464 467 static void pseries_msi_shutdown(struct irq_data *d)
-1
arch/um/drivers/Kconfig
··· 381 381 select UML_IOMEM_EMULATION 382 382 select UML_DMA_EMULATION 383 383 select PCI_MSI 384 - select PCI_MSI_IRQ_DOMAIN 385 384 select PCI_LOCKLESS_CONFIG 386 385 387 386 config UML_PCI_OVER_VIRTIO_DEVICE_ID
+1 -1
arch/um/include/asm/pci.h
··· 7 7 /* Generic PCI */ 8 8 #include <asm-generic/pci.h> 9 9 10 - #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 10 + #ifdef CONFIG_PCI_MSI 11 11 /* 12 12 * This is a bit of an annoying hack, and it assumes we only have 13 13 * the virt-pci (if anything). Which is true, but still.
-1
arch/x86/Kconfig
··· 1110 1110 def_bool y 1111 1111 depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI 1112 1112 select IRQ_DOMAIN_HIERARCHY 1113 - select PCI_MSI_IRQ_DOMAIN if PCI_MSI 1114 1113 1115 1114 config X86_IO_APIC 1116 1115 def_bool y
+9
arch/x86/include/asm/hyperv_timer.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_X86_HYPERV_TIMER_H 3 + #define _ASM_X86_HYPERV_TIMER_H 4 + 5 + #include <asm/msr.h> 6 + 7 + #define hv_get_raw_timer() rdtsc_ordered() 8 + 9 + #endif
-4
arch/x86/include/asm/irq_remapping.h
··· 44 44 extern int irq_remap_enable_fault_handling(void); 45 45 extern void panic_if_irq_remap(const char *msg); 46 46 47 - /* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */ 48 - extern struct irq_domain * 49 - arch_create_remap_msi_irq_domain(struct irq_domain *par, const char *n, int id); 50 - 51 47 /* Get parent irqdomain for interrupt remapping irqdomain */ 52 48 static inline struct irq_domain *arch_get_ir_parent_domain(void) 53 49 {
+1 -3
arch/x86/include/asm/irqdomain.h
··· 7 7 8 8 #ifdef CONFIG_X86_LOCAL_APIC 9 9 enum { 10 - /* Allocate contiguous CPU vectors */ 11 - X86_IRQ_ALLOC_CONTIGUOUS_VECTORS = 0x1, 12 - X86_IRQ_ALLOC_LEGACY = 0x2, 10 + X86_IRQ_ALLOC_LEGACY = 0x1, 13 11 }; 14 12 15 13 extern int x86_fwspec_is_ioapic(struct irq_fwspec *fwspec);
-2
arch/x86/include/asm/mshyperv.h
··· 19 19 struct hv_guest_mapping_flush_list *flush, 20 20 void *data); 21 21 22 - #define hv_get_raw_timer() rdtsc_ordered() 23 - 24 22 void hyperv_vector_handler(struct pt_regs *regs); 25 23 26 24 #if IS_ENABLED(CONFIG_HYPERV)
+6
arch/x86/include/asm/msi.h
··· 62 62 struct msi_msg; 63 63 u32 x86_msi_msg_get_destid(struct msi_msg *msg, bool extid); 64 64 65 + #define X86_VECTOR_MSI_FLAGS_SUPPORTED \ 66 + (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX | MSI_FLAG_PCI_MSIX_ALLOC_DYN) 67 + 68 + #define X86_VECTOR_MSI_FLAGS_REQUIRED \ 69 + (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS) 70 + 65 71 #endif /* _ASM_X86_MSI_H */
+3 -2
arch/x86/include/asm/pci.h
··· 21 21 #ifdef CONFIG_X86_64 22 22 void *iommu; /* IOMMU private data */ 23 23 #endif 24 - #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 24 + #ifdef CONFIG_PCI_MSI 25 25 void *fwnode; /* IRQ domain for MSI assignment */ 26 26 #endif 27 27 #if IS_ENABLED(CONFIG_VMD) ··· 52 52 } 53 53 #endif 54 54 55 - #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 55 + #ifdef CONFIG_PCI_MSI 56 56 static inline void *_pci_root_bus_fwnode(struct pci_bus *bus) 57 57 { 58 58 return to_pci_sysdata(bus)->fwnode; ··· 92 92 struct irq_routing_table *pcibios_get_irq_routing_table(void); 93 93 int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); 94 94 95 + bool pci_dev_has_default_msi_parent_domain(struct pci_dev *dev); 95 96 96 97 #define HAVE_PCI_MMAP 97 98 #define arch_can_pci_mmap_wc() pat_enabled()
+130 -83
arch/x86/kernel/apic/msi.c
··· 142 142 return ret; 143 143 } 144 144 145 - /* 146 - * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, 147 - * which implement the MSI or MSI-X Capability Structure. 145 + /** 146 + * pci_dev_has_default_msi_parent_domain - Check whether the device has the default 147 + * MSI parent domain associated 148 + * @dev: Pointer to the PCI device 148 149 */ 149 - static struct irq_chip pci_msi_controller = { 150 - .name = "PCI-MSI", 151 - .irq_unmask = pci_msi_unmask_irq, 152 - .irq_mask = pci_msi_mask_irq, 153 - .irq_ack = irq_chip_ack_parent, 154 - .irq_retrigger = irq_chip_retrigger_hierarchy, 155 - .irq_set_affinity = msi_set_affinity, 156 - .flags = IRQCHIP_SKIP_SET_WAKE | 157 - IRQCHIP_AFFINITY_PRE_STARTUP, 158 - }; 159 - 160 - int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, 161 - msi_alloc_info_t *arg) 150 + bool pci_dev_has_default_msi_parent_domain(struct pci_dev *dev) 162 151 { 163 - init_irq_alloc_info(arg, NULL); 164 - if (to_pci_dev(dev)->msix_enabled) { 165 - arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX; 166 - } else { 167 - arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI; 168 - arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS; 152 + struct irq_domain *domain = dev_get_msi_domain(&dev->dev); 153 + 154 + if (!domain) 155 + domain = dev_get_msi_domain(&dev->bus->dev); 156 + if (!domain) 157 + return false; 158 + 159 + return domain == x86_vector_domain; 160 + } 161 + 162 + /** 163 + * x86_msi_prepare - Setup of msi_alloc_info_t for allocations 164 + * @domain: The domain for which this setup happens 165 + * @dev: The device for which interrupts are allocated 166 + * @nvec: The number of vectors to allocate 167 + * @alloc: The allocation info structure to initialize 168 + * 169 + * This function is to be used for all types of MSI domains above the x86 170 + * vector domain and any intermediates. It is always invoked from the 171 + * top level interrupt domain. The domain specific allocation 172 + * functionality is determined via the @domain's bus token which allows to 173 + * map the X86 specific allocation type. 174 + */ 175 + static int x86_msi_prepare(struct irq_domain *domain, struct device *dev, 176 + int nvec, msi_alloc_info_t *alloc) 177 + { 178 + struct msi_domain_info *info = domain->host_data; 179 + 180 + init_irq_alloc_info(alloc, NULL); 181 + 182 + switch (info->bus_token) { 183 + case DOMAIN_BUS_PCI_DEVICE_MSI: 184 + alloc->type = X86_IRQ_ALLOC_TYPE_PCI_MSI; 185 + return 0; 186 + case DOMAIN_BUS_PCI_DEVICE_MSIX: 187 + case DOMAIN_BUS_PCI_DEVICE_IMS: 188 + alloc->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX; 189 + return 0; 190 + default: 191 + return -EINVAL; 192 + } 193 + } 194 + 195 + /** 196 + * x86_init_dev_msi_info - Domain info setup for MSI domains 197 + * @dev: The device for which the domain should be created 198 + * @domain: The (root) domain providing this callback 199 + * @real_parent: The real parent domain of the to initialize domain 200 + * @info: The domain info for the to initialize domain 201 + * 202 + * This function is to be used for all types of MSI domains above the x86 203 + * vector domain and any intermediates. The domain specific functionality 204 + * is determined via the @real_parent. 205 + */ 206 + static bool x86_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 207 + struct irq_domain *real_parent, struct msi_domain_info *info) 208 + { 209 + const struct msi_parent_ops *pops = real_parent->msi_parent_ops; 210 + 211 + /* MSI parent domain specific settings */ 212 + switch (real_parent->bus_token) { 213 + case DOMAIN_BUS_ANY: 214 + /* Only the vector domain can have the ANY token */ 215 + if (WARN_ON_ONCE(domain != real_parent)) 216 + return false; 217 + info->chip->irq_set_affinity = msi_set_affinity; 218 + /* See msi_set_affinity() for the gory details */ 219 + info->flags |= MSI_FLAG_NOMASK_QUIRK; 220 + break; 221 + case DOMAIN_BUS_DMAR: 222 + case DOMAIN_BUS_AMDVI: 223 + break; 224 + default: 225 + WARN_ON_ONCE(1); 226 + return false; 169 227 } 170 228 171 - return 0; 229 + /* Is the target supported? */ 230 + switch(info->bus_token) { 231 + case DOMAIN_BUS_PCI_DEVICE_MSI: 232 + case DOMAIN_BUS_PCI_DEVICE_MSIX: 233 + break; 234 + case DOMAIN_BUS_PCI_DEVICE_IMS: 235 + if (!(pops->supported_flags & MSI_FLAG_PCI_IMS)) 236 + return false; 237 + break; 238 + default: 239 + WARN_ON_ONCE(1); 240 + return false; 241 + } 242 + 243 + /* 244 + * Mask out the domain specific MSI feature flags which are not 245 + * supported by the real parent. 246 + */ 247 + info->flags &= pops->supported_flags; 248 + /* Enforce the required flags */ 249 + info->flags |= X86_VECTOR_MSI_FLAGS_REQUIRED; 250 + 251 + /* This is always invoked from the top level MSI domain! */ 252 + info->ops->msi_prepare = x86_msi_prepare; 253 + 254 + info->chip->irq_ack = irq_chip_ack_parent; 255 + info->chip->irq_retrigger = irq_chip_retrigger_hierarchy; 256 + info->chip->flags |= IRQCHIP_SKIP_SET_WAKE | 257 + IRQCHIP_AFFINITY_PRE_STARTUP; 258 + 259 + info->handler = handle_edge_irq; 260 + info->handler_name = "edge"; 261 + 262 + return true; 172 263 } 173 - EXPORT_SYMBOL_GPL(pci_msi_prepare); 174 264 175 - static struct msi_domain_ops pci_msi_domain_ops = { 176 - .msi_prepare = pci_msi_prepare, 177 - }; 178 - 179 - static struct msi_domain_info pci_msi_domain_info = { 180 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 181 - MSI_FLAG_PCI_MSIX, 182 - .ops = &pci_msi_domain_ops, 183 - .chip = &pci_msi_controller, 184 - .handler = handle_edge_irq, 185 - .handler_name = "edge", 265 + static const struct msi_parent_ops x86_vector_msi_parent_ops = { 266 + .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED, 267 + .init_dev_msi_info = x86_init_dev_msi_info, 186 268 }; 187 269 188 270 struct irq_domain * __init native_create_pci_msi_domain(void) 189 271 { 190 - struct fwnode_handle *fn; 191 - struct irq_domain *d; 192 - 193 272 if (disable_apic) 194 273 return NULL; 195 274 196 - fn = irq_domain_alloc_named_fwnode("PCI-MSI"); 197 - if (!fn) 198 - return NULL; 199 - 200 - d = pci_msi_create_irq_domain(fn, &pci_msi_domain_info, 201 - x86_vector_domain); 202 - if (!d) { 203 - irq_domain_free_fwnode(fn); 204 - pr_warn("Failed to initialize PCI-MSI irqdomain.\n"); 205 - } else { 206 - d->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK; 207 - } 208 - return d; 275 + x86_vector_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 276 + x86_vector_domain->msi_parent_ops = &x86_vector_msi_parent_ops; 277 + return x86_vector_domain; 209 278 } 210 279 211 280 void __init x86_create_pci_msi_domain(void) ··· 282 213 x86_pci_msi_default_domain = x86_init.irqs.create_pci_msi_domain(); 283 214 } 284 215 285 - #ifdef CONFIG_IRQ_REMAP 286 - static struct irq_chip pci_msi_ir_controller = { 287 - .name = "IR-PCI-MSI", 288 - .irq_unmask = pci_msi_unmask_irq, 289 - .irq_mask = pci_msi_mask_irq, 290 - .irq_ack = irq_chip_ack_parent, 291 - .irq_retrigger = irq_chip_retrigger_hierarchy, 292 - .flags = IRQCHIP_SKIP_SET_WAKE | 293 - IRQCHIP_AFFINITY_PRE_STARTUP, 294 - }; 295 - 296 - static struct msi_domain_info pci_msi_ir_domain_info = { 297 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 298 - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, 299 - .ops = &pci_msi_domain_ops, 300 - .chip = &pci_msi_ir_controller, 301 - .handler = handle_edge_irq, 302 - .handler_name = "edge", 303 - }; 304 - 305 - struct irq_domain *arch_create_remap_msi_irq_domain(struct irq_domain *parent, 306 - const char *name, int id) 216 + /* Keep around for hyperV */ 217 + int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, 218 + msi_alloc_info_t *arg) 307 219 { 308 - struct fwnode_handle *fn; 309 - struct irq_domain *d; 220 + init_irq_alloc_info(arg, NULL); 310 221 311 - fn = irq_domain_alloc_named_id_fwnode(name, id); 312 - if (!fn) 313 - return NULL; 314 - d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent); 315 - if (!d) 316 - irq_domain_free_fwnode(fn); 317 - return d; 222 + if (to_pci_dev(dev)->msix_enabled) 223 + arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX; 224 + else 225 + arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI; 226 + return 0; 318 227 } 319 - #endif 228 + EXPORT_SYMBOL_GPL(pci_msi_prepare); 320 229 321 230 #ifdef CONFIG_DMAR_TABLE 322 231 /*
-4
arch/x86/kernel/apic/vector.c
··· 539 539 if (disable_apic) 540 540 return -ENXIO; 541 541 542 - /* Currently vector allocator can't guarantee contiguous allocations */ 543 - if ((info->flags & X86_IRQ_ALLOC_CONTIGUOUS_VECTORS) && nr_irqs > 1) 544 - return -ENOSYS; 545 - 546 542 /* 547 543 * Catch any attempt to touch the cascade interrupt on a PIC 548 544 * equipped system.
+4 -2
drivers/acpi/pci_irq.c
··· 387 387 u8 pin; 388 388 int triggering = ACPI_LEVEL_SENSITIVE; 389 389 /* 390 - * On ARM systems with the GIC interrupt model, level interrupts 390 + * On ARM systems with the GIC interrupt model, or LoongArch 391 + * systems with the LPIC interrupt model, level interrupts 391 392 * are always polarity high by specification; PCI legacy 392 393 * IRQs lines are inverted before reaching the interrupt 393 394 * controller and must therefore be considered active high 394 395 * as default. 395 396 */ 396 - int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 397 + int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC || 398 + acpi_irq_model == ACPI_IRQ_MODEL_LPIC ? 397 399 ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; 398 400 char *link = NULL; 399 401 char link_desc[16];
+1 -1
drivers/base/Makefile
··· 22 22 obj-$(CONFIG_SOC_BUS) += soc.o 23 23 obj-$(CONFIG_PINCTRL) += pinctrl.o 24 24 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o 25 - obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o 25 + obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o 26 26 obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o 27 27 obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o 28 28 obj-$(CONFIG_ACPI) += physical_location.o
+3 -3
drivers/base/platform-msi.c
··· 213 213 if (err) 214 214 return err; 215 215 216 - err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec); 216 + err = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1); 217 217 if (err) 218 218 platform_msi_free_priv_data(dev); 219 219 ··· 227 227 */ 228 228 void platform_msi_domain_free_irqs(struct device *dev) 229 229 { 230 - msi_domain_free_irqs(dev->msi.domain, dev); 230 + msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); 231 231 platform_msi_free_priv_data(dev); 232 232 } 233 233 EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs); ··· 325 325 326 326 msi_lock_descs(data->dev); 327 327 irq_domain_free_irqs_common(domain, virq, nr_irqs); 328 - msi_free_msi_descs_range(data->dev, MSI_DESC_ALL, virq, virq + nr_irqs - 1); 328 + msi_free_msi_descs_range(data->dev, virq, virq + nr_irqs - 1); 329 329 msi_unlock_descs(data->dev); 330 330 } 331 331
+1 -1
drivers/bus/fsl-mc/Kconfig
··· 8 8 config FSL_MC_BUS 9 9 bool "QorIQ DPAA2 fsl-mc bus driver" 10 10 depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86_LOCAL_APIC || PPC))) 11 - select GENERIC_MSI_IRQ_DOMAIN 11 + select GENERIC_MSI_IRQ 12 12 help 13 13 Driver to enable the bus infrastructure for the QorIQ DPAA2 14 14 architecture. The fsl-mc bus driver handles discovery of
-1
drivers/bus/fsl-mc/dprc-driver.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/slab.h> 13 13 #include <linux/interrupt.h> 14 - #include <linux/msi.h> 15 14 #include <linux/fsl/mc.h> 16 15 17 16 #include "fsl-mc-private.h"
-1
drivers/bus/fsl-mc/fsl-mc-bus.c
··· 17 17 #include <linux/slab.h> 18 18 #include <linux/limits.h> 19 19 #include <linux/bitops.h> 20 - #include <linux/msi.h> 21 20 #include <linux/dma-mapping.h> 22 21 #include <linux/acpi.h> 23 22 #include <linux/iommu.h>
+3 -22
drivers/bus/fsl-mc/fsl-mc-msi.c
··· 213 213 214 214 int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count) 215 215 { 216 - struct irq_domain *msi_domain; 217 - int error; 216 + int error = msi_setup_device_data(dev); 218 217 219 - msi_domain = dev_get_msi_domain(dev); 220 - if (!msi_domain) 221 - return -EINVAL; 222 - 223 - error = msi_setup_device_data(dev); 224 - if (error) 225 - return error; 226 - 227 - msi_lock_descs(dev); 228 - if (msi_first_desc(dev, MSI_DESC_ALL)) 229 - error = -EINVAL; 230 - msi_unlock_descs(dev); 231 218 if (error) 232 219 return error; 233 220 ··· 222 235 * NOTE: Calling this function will trigger the invocation of the 223 236 * its_fsl_mc_msi_prepare() callback 224 237 */ 225 - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); 238 + error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, irq_count - 1); 226 239 227 240 if (error) 228 241 dev_err(dev, "Failed to allocate IRQs\n"); ··· 231 244 232 245 void fsl_mc_msi_domain_free_irqs(struct device *dev) 233 246 { 234 - struct irq_domain *msi_domain; 235 - 236 - msi_domain = dev_get_msi_domain(dev); 237 - if (!msi_domain) 238 - return; 239 - 240 - msi_domain_free_irqs(msi_domain, dev); 247 + msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); 241 248 }
+1 -1
drivers/dma/Kconfig
··· 462 462 select DMA_ENGINE 463 463 select DMA_ENGINE_RAID 464 464 select ASYNC_TX_ENABLE_CHANNEL_SWITCH 465 - select GENERIC_MSI_IRQ_DOMAIN 465 + select GENERIC_MSI_IRQ 466 466 help 467 467 Enable support for the Marvell version 2 XOR engine. 468 468
+4 -4
drivers/dma/qcom/hidma.c
··· 610 610 return hidma_ll_inthandler(chirq, lldev); 611 611 } 612 612 613 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 613 + #ifdef CONFIG_GENERIC_MSI_IRQ 614 614 static irqreturn_t hidma_chirq_handler_msi(int chirq, void *arg) 615 615 { 616 616 struct hidma_lldev **lldevp = arg; ··· 671 671 return device_create_file(dev->ddev.dev, dev->chid_attrs); 672 672 } 673 673 674 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 674 + #ifdef CONFIG_GENERIC_MSI_IRQ 675 675 static void hidma_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) 676 676 { 677 677 struct device *dev = msi_desc_to_dev(desc); ··· 687 687 688 688 static void hidma_free_msis(struct hidma_dev *dmadev) 689 689 { 690 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 690 + #ifdef CONFIG_GENERIC_MSI_IRQ 691 691 struct device *dev = dmadev->ddev.dev; 692 692 int i, virq; 693 693 ··· 704 704 static int hidma_request_msi(struct hidma_dev *dmadev, 705 705 struct platform_device *pdev) 706 706 { 707 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 707 + #ifdef CONFIG_GENERIC_MSI_IRQ 708 708 int rc, i, virq; 709 709 710 710 rc = platform_msi_domain_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS,
+1
drivers/hv/vmbus_drv.c
··· 36 36 #include <linux/dma-map-ops.h> 37 37 #include <linux/pci.h> 38 38 #include <clocksource/hyperv_timer.h> 39 + #include <asm/mshyperv.h> 39 40 #include "hyperv_vmbus.h" 40 41 41 42 struct vmbus_dynid {
+1 -1
drivers/iommu/Kconfig
··· 389 389 depends on ARM64 390 390 select IOMMU_API 391 391 select IOMMU_IO_PGTABLE_LPAE 392 - select GENERIC_MSI_IRQ_DOMAIN 392 + select GENERIC_MSI_IRQ 393 393 help 394 394 Support for implementations of the ARM System MMU architecture 395 395 version 3 providing translation support to a PCIe root complex.
-1
drivers/iommu/amd/amd_iommu_types.h
··· 734 734 u8 max_counters; 735 735 #ifdef CONFIG_IRQ_REMAP 736 736 struct irq_domain *ir_domain; 737 - struct irq_domain *msi_domain; 738 737 739 738 struct amd_irte_ops *irte_ops; 740 739 #endif
+28 -16
drivers/iommu/amd/iommu.c
··· 812 812 amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) 813 813 { 814 814 if (!irq_remapping_enabled || !dev_is_pci(dev) || 815 - pci_dev_has_special_msi_domain(to_pci_dev(dev))) 815 + !pci_dev_has_default_msi_parent_domain(to_pci_dev(dev))) 816 816 return; 817 817 818 - dev_set_msi_domain(dev, iommu->msi_domain); 818 + dev_set_msi_domain(dev, iommu->ir_domain); 819 819 } 820 820 821 821 #else /* CONFIG_IRQ_REMAP */ ··· 3294 3294 3295 3295 if (!info) 3296 3296 return -EINVAL; 3297 - if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_PCI_MSI && 3298 - info->type != X86_IRQ_ALLOC_TYPE_PCI_MSIX) 3297 + if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_PCI_MSI) 3299 3298 return -EINVAL; 3300 - 3301 - /* 3302 - * With IRQ remapping enabled, don't need contiguous CPU vectors 3303 - * to support multiple MSI interrupts. 3304 - */ 3305 - if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI) 3306 - info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS; 3307 3299 3308 3300 sbdf = get_devid(info); 3309 3301 if (sbdf < 0) ··· 3648 3656 .irq_compose_msi_msg = ir_compose_msi_msg, 3649 3657 }; 3650 3658 3659 + static const struct msi_parent_ops amdvi_msi_parent_ops = { 3660 + .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED | 3661 + MSI_FLAG_MULTI_PCI_MSI | 3662 + MSI_FLAG_PCI_IMS, 3663 + .prefix = "IR-", 3664 + .init_dev_msi_info = msi_parent_init_dev_msi_info, 3665 + }; 3666 + 3667 + static const struct msi_parent_ops virt_amdvi_msi_parent_ops = { 3668 + .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED | 3669 + MSI_FLAG_MULTI_PCI_MSI, 3670 + .prefix = "vIR-", 3671 + .init_dev_msi_info = msi_parent_init_dev_msi_info, 3672 + }; 3673 + 3651 3674 int amd_iommu_create_irq_domain(struct amd_iommu *iommu) 3652 3675 { 3653 3676 struct fwnode_handle *fn; ··· 3670 3663 fn = irq_domain_alloc_named_id_fwnode("AMD-IR", iommu->index); 3671 3664 if (!fn) 3672 3665 return -ENOMEM; 3673 - iommu->ir_domain = irq_domain_create_tree(fn, &amd_ir_domain_ops, iommu); 3666 + iommu->ir_domain = irq_domain_create_hierarchy(arch_get_ir_parent_domain(), 0, 0, 3667 + fn, &amd_ir_domain_ops, iommu); 3674 3668 if (!iommu->ir_domain) { 3675 3669 irq_domain_free_fwnode(fn); 3676 3670 return -ENOMEM; 3677 3671 } 3678 3672 3679 - iommu->ir_domain->parent = arch_get_ir_parent_domain(); 3680 - iommu->msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain, 3681 - "AMD-IR-MSI", 3682 - iommu->index); 3673 + irq_domain_update_bus_token(iommu->ir_domain, DOMAIN_BUS_AMDVI); 3674 + iommu->ir_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 3675 + 3676 + if (amd_iommu_np_cache) 3677 + iommu->ir_domain->msi_parent_ops = &virt_amdvi_msi_parent_ops; 3678 + else 3679 + iommu->ir_domain->msi_parent_ops = &amdvi_msi_parent_ops; 3680 + 3683 3681 return 0; 3684 3682 } 3685 3683
-1
drivers/iommu/intel/iommu.h
··· 600 600 #ifdef CONFIG_IRQ_REMAP 601 601 struct ir_table *ir_table; /* Interrupt remapping info */ 602 602 struct irq_domain *ir_domain; 603 - struct irq_domain *ir_msi_domain; 604 603 #endif 605 604 struct iommu_device iommu; /* IOMMU core code handle */ 606 605 int node;
+27 -25
drivers/iommu/intel/irq_remapping.c
··· 82 82 83 83 static void iommu_disable_irq_remapping(struct intel_iommu *iommu); 84 84 static int __init parse_ioapics_under_ir(void); 85 + static const struct msi_parent_ops dmar_msi_parent_ops, virt_dmar_msi_parent_ops; 85 86 86 87 static bool ir_pre_enabled(struct intel_iommu *iommu) 87 88 { ··· 231 230 { 232 231 struct dmar_drhd_unit *drhd = dmar_find_matched_drhd_unit(dev); 233 232 234 - return drhd ? drhd->iommu->ir_msi_domain : NULL; 233 + return drhd ? drhd->iommu->ir_domain : NULL; 235 234 } 236 235 237 236 static int clear_entries(struct irq_2_iommu *irq_iommu) ··· 574 573 pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); 575 574 goto out_free_fwnode; 576 575 } 577 - iommu->ir_msi_domain = 578 - arch_create_remap_msi_irq_domain(iommu->ir_domain, 579 - "INTEL-IR-MSI", 580 - iommu->seq_id); 576 + 577 + irq_domain_update_bus_token(iommu->ir_domain, DOMAIN_BUS_DMAR); 578 + iommu->ir_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 579 + 580 + if (cap_caching_mode(iommu->cap)) 581 + iommu->ir_domain->msi_parent_ops = &virt_dmar_msi_parent_ops; 582 + else 583 + iommu->ir_domain->msi_parent_ops = &dmar_msi_parent_ops; 581 584 582 585 ir_table->base = page_address(pages); 583 586 ir_table->bitmap = bitmap; ··· 625 620 return 0; 626 621 627 622 out_free_ir_domain: 628 - if (iommu->ir_msi_domain) 629 - irq_domain_remove(iommu->ir_msi_domain); 630 - iommu->ir_msi_domain = NULL; 631 623 irq_domain_remove(iommu->ir_domain); 632 624 iommu->ir_domain = NULL; 633 625 out_free_fwnode: ··· 646 644 struct fwnode_handle *fn; 647 645 648 646 if (iommu && iommu->ir_table) { 649 - if (iommu->ir_msi_domain) { 650 - fn = iommu->ir_msi_domain->fwnode; 651 - 652 - irq_domain_remove(iommu->ir_msi_domain); 653 - irq_domain_free_fwnode(fn); 654 - iommu->ir_msi_domain = NULL; 655 - } 656 647 if (iommu->ir_domain) { 657 648 fn = iommu->ir_domain->fwnode; 658 649 ··· 1102 1107 */ 1103 1108 void intel_irq_remap_add_device(struct dmar_pci_notify_info *info) 1104 1109 { 1105 - if (!irq_remapping_enabled || pci_dev_has_special_msi_domain(info->dev)) 1110 + if (!irq_remapping_enabled || !pci_dev_has_default_msi_parent_domain(info->dev)) 1106 1111 return; 1107 1112 1108 1113 dev_set_msi_domain(&info->dev->dev, map_dev_to_ir(info->dev)); ··· 1329 1334 1330 1335 if (!info || !iommu) 1331 1336 return -EINVAL; 1332 - if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_PCI_MSI && 1333 - info->type != X86_IRQ_ALLOC_TYPE_PCI_MSIX) 1337 + if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_PCI_MSI) 1334 1338 return -EINVAL; 1335 - 1336 - /* 1337 - * With IRQ remapping enabled, don't need contiguous CPU vectors 1338 - * to support multiple MSI interrupts. 1339 - */ 1340 - if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI) 1341 - info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS; 1342 1339 1343 1340 ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg); 1344 1341 if (ret < 0) ··· 1430 1443 .free = intel_irq_remapping_free, 1431 1444 .activate = intel_irq_remapping_activate, 1432 1445 .deactivate = intel_irq_remapping_deactivate, 1446 + }; 1447 + 1448 + static const struct msi_parent_ops dmar_msi_parent_ops = { 1449 + .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED | 1450 + MSI_FLAG_MULTI_PCI_MSI | 1451 + MSI_FLAG_PCI_IMS, 1452 + .prefix = "IR-", 1453 + .init_dev_msi_info = msi_parent_init_dev_msi_info, 1454 + }; 1455 + 1456 + static const struct msi_parent_ops virt_dmar_msi_parent_ops = { 1457 + .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED | 1458 + MSI_FLAG_MULTI_PCI_MSI, 1459 + .prefix = "vIR-", 1460 + .init_dev_msi_info = msi_parent_init_dev_msi_info, 1433 1461 }; 1434 1462 1435 1463 /*
-1
drivers/iommu/of_iommu.c
··· 9 9 #include <linux/iommu.h> 10 10 #include <linux/limits.h> 11 11 #include <linux/module.h> 12 - #include <linux/msi.h> 13 12 #include <linux/of.h> 14 13 #include <linux/of_iommu.h> 15 14 #include <linux/of_pci.h>
+5 -4
drivers/irqchip/Kconfig
··· 38 38 39 39 config ARM_GIC_V3_ITS 40 40 bool 41 - select GENERIC_MSI_IRQ_DOMAIN 41 + select GENERIC_MSI_IRQ 42 42 default ARM_GIC_V3 43 43 44 44 config ARM_GIC_V3_ITS_PCI ··· 86 86 87 87 config AL_FIC 88 88 bool "Amazon's Annapurna Labs Fabric Interrupt Controller" 89 - depends on OF || COMPILE_TEST 89 + depends on OF 90 90 select GENERIC_IRQ_CHIP 91 91 select IRQ_DOMAIN 92 92 help ··· 375 375 376 376 config MVEBU_ODMI 377 377 bool 378 - select GENERIC_MSI_IRQ_DOMAIN 378 + select GENERIC_MSI_IRQ 379 379 380 380 config MVEBU_PIC 381 381 bool ··· 488 488 default m if ARCH_MXC 489 489 select IRQ_DOMAIN 490 490 select IRQ_DOMAIN_HIERARCHY 491 - select GENERIC_MSI_IRQ_DOMAIN 491 + select GENERIC_MSI_IRQ 492 492 help 493 493 Provide a driver for the i.MX Messaging Unit block used as a 494 494 CPU-to-CPU MSI controller. This requires a specially crafted DT ··· 576 576 select GENERIC_IRQ_CHIP 577 577 select IRQ_DOMAIN 578 578 select GENERIC_IRQ_EFFECTIVE_AFF_MASK 579 + select LOONGSON_HTVEC 579 580 select LOONGSON_LIOINTC 580 581 select LOONGSON_EIOINTC 581 582 select LOONGSON_PCH_PIC
+3 -3
drivers/irqchip/irq-apple-aic.c
··· 248 248 bool fast_ipi; 249 249 }; 250 250 251 - static const struct aic_info aic1_info = { 251 + static const struct aic_info aic1_info __initconst = { 252 252 .version = 1, 253 253 254 254 .event = AIC_EVENT, 255 255 .target_cpu = AIC_TARGET_CPU, 256 256 }; 257 257 258 - static const struct aic_info aic1_fipi_info = { 258 + static const struct aic_info aic1_fipi_info __initconst = { 259 259 .version = 1, 260 260 261 261 .event = AIC_EVENT, ··· 264 264 .fast_ipi = true, 265 265 }; 266 266 267 - static const struct aic_info aic2_info = { 267 + static const struct aic_info aic2_info __initconst = { 268 268 .version = 2, 269 269 270 270 .irq_cfg = AIC2_IRQ_CFG,
+1 -1
drivers/irqchip/irq-gic-pm.c
··· 102 102 103 103 pm_runtime_enable(dev); 104 104 105 - ret = pm_runtime_get_sync(dev); 105 + ret = pm_runtime_resume_and_get(dev); 106 106 if (ret < 0) 107 107 goto rpm_disable; 108 108
+6 -5
drivers/irqchip/irq-gic-v2m.c
··· 24 24 #include <linux/slab.h> 25 25 #include <linux/spinlock.h> 26 26 #include <linux/irqchip/arm-gic.h> 27 + #include <linux/irqchip/arm-gic-common.h> 27 28 28 29 /* 29 30 * MSI_TYPER: ··· 263 262 .chip = &gicv2m_pmsi_irq_chip, 264 263 }; 265 264 266 - static void gicv2m_teardown(void) 265 + static void __init gicv2m_teardown(void) 267 266 { 268 267 struct v2m_data *v2m, *tmp; 269 268 ··· 278 277 } 279 278 } 280 279 281 - static int gicv2m_allocate_domains(struct irq_domain *parent) 280 + static __init int gicv2m_allocate_domains(struct irq_domain *parent) 282 281 { 283 282 struct irq_domain *inner_domain, *pci_domain, *plat_domain; 284 283 struct v2m_data *v2m; ··· 405 404 return ret; 406 405 } 407 406 408 - static const struct of_device_id gicv2m_device_id[] = { 407 + static __initconst struct of_device_id gicv2m_device_id[] = { 409 408 { .compatible = "arm,gic-v2m-frame", }, 410 409 {}, 411 410 }; ··· 455 454 #ifdef CONFIG_ACPI 456 455 static int acpi_num_msi; 457 456 458 - static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev) 457 + static __init struct fwnode_handle *gicv2m_get_fwnode(struct device *dev) 459 458 { 460 459 struct v2m_data *data; 461 460 ··· 470 469 return data->fwnode; 471 470 } 472 471 473 - static bool acpi_check_amazon_graviton_quirks(void) 472 + static __init bool acpi_check_amazon_graviton_quirks(void) 474 473 { 475 474 static struct acpi_table_madt *madt; 476 475 acpi_status status;
+2 -1
drivers/irqchip/irq-gic-v3.c
··· 12 12 #include <linux/delay.h> 13 13 #include <linux/interrupt.h> 14 14 #include <linux/irqdomain.h> 15 + #include <linux/kstrtox.h> 15 16 #include <linux/of.h> 16 17 #include <linux/of_address.h> 17 18 #include <linux/of_irq.h> ··· 1172 1171 1173 1172 static int __init gicv3_nolpi_cfg(char *buf) 1174 1173 { 1175 - return strtobool(buf, &gicv3_nolpi); 1174 + return kstrtobool(buf, &gicv3_nolpi); 1176 1175 } 1177 1176 early_param("irqchip.gicv3_nolpi", gicv3_nolpi_cfg); 1178 1177
+4 -3
drivers/irqchip/irq-gic.c
··· 19 19 */ 20 20 #include <linux/init.h> 21 21 #include <linux/kernel.h> 22 + #include <linux/kstrtox.h> 22 23 #include <linux/err.h> 23 24 #include <linux/module.h> 24 25 #include <linux/list.h> ··· 402 401 { 403 402 struct gic_chip_data *gic = irq_data_get_irq_chip_data(d); 404 403 405 - if (gic->domain->dev) 406 - seq_printf(p, gic->domain->dev->of_node->name); 404 + if (gic->domain->pm_dev) 405 + seq_printf(p, gic->domain->pm_dev->of_node->name); 407 406 else 408 407 seq_printf(p, "GIC-%d", (int)(gic - &gic_data[0])); 409 408 } ··· 1333 1332 1334 1333 static int __init gicv2_force_probe_cfg(char *buf) 1335 1334 { 1336 - return strtobool(buf, &gicv2_force_probe); 1335 + return kstrtobool(buf, &gicv2_force_probe); 1337 1336 } 1338 1337 early_param("irqchip.gicv2_force_probe", gicv2_force_probe_cfg); 1339 1338
+36 -12
drivers/irqchip/irq-loongarch-cpu.c
··· 92 92 .xlate = irq_domain_xlate_onecell, 93 93 }; 94 94 95 - static int __init 96 - liointc_parse_madt(union acpi_subtable_headers *header, 97 - const unsigned long end) 95 + #ifdef CONFIG_OF 96 + static int __init cpuintc_of_init(struct device_node *of_node, 97 + struct device_node *parent) 98 + { 99 + cpuintc_handle = of_node_to_fwnode(of_node); 100 + 101 + irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM, 102 + &loongarch_cpu_intc_irq_domain_ops, NULL); 103 + if (!irq_domain) 104 + panic("Failed to add irqdomain for loongarch CPU"); 105 + 106 + set_handle_irq(&handle_cpu_irq); 107 + 108 + return 0; 109 + } 110 + IRQCHIP_DECLARE(cpu_intc, "loongson,cpu-interrupt-controller", cpuintc_of_init); 111 + #endif 112 + 113 + static int __init liointc_parse_madt(union acpi_subtable_headers *header, 114 + const unsigned long end) 98 115 { 99 116 struct acpi_madt_lio_pic *liointc_entry = (struct acpi_madt_lio_pic *)header; 100 117 101 118 return liointc_acpi_init(irq_domain, liointc_entry); 102 119 } 103 120 104 - static int __init 105 - eiointc_parse_madt(union acpi_subtable_headers *header, 106 - const unsigned long end) 121 + static int __init eiointc_parse_madt(union acpi_subtable_headers *header, 122 + const unsigned long end) 107 123 { 108 124 struct acpi_madt_eio_pic *eiointc_entry = (struct acpi_madt_eio_pic *)header; 109 125 ··· 128 112 129 113 static int __init acpi_cascade_irqdomain_init(void) 130 114 { 131 - acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC, 132 - liointc_parse_madt, 0); 133 - acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, 134 - eiointc_parse_madt, 0); 115 + int r; 116 + 117 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC, liointc_parse_madt, 0); 118 + if (r < 0) 119 + return r; 120 + 121 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, eiointc_parse_madt, 0); 122 + if (r < 0) 123 + return r; 124 + 135 125 return 0; 136 126 } 137 127 138 128 static int __init cpuintc_acpi_init(union acpi_subtable_headers *header, 139 129 const unsigned long end) 140 130 { 131 + int ret; 132 + 141 133 if (irq_domain) 142 134 return 0; 143 135 ··· 163 139 set_handle_irq(&handle_cpu_irq); 164 140 acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id); 165 141 acpi_set_gsi_to_irq_fallback(lpic_gsi_to_irq); 166 - acpi_cascade_irqdomain_init(); 142 + ret = acpi_cascade_irqdomain_init(); 167 143 168 - return 0; 144 + return ret; 169 145 } 170 146 171 147 IRQCHIP_ACPI_DECLARE(cpuintc_v1, ACPI_MADT_TYPE_CORE_PIC,
+50 -13
drivers/irqchip/irq-loongson-eiointc.c
··· 17 17 #include <linux/of_address.h> 18 18 #include <linux/of_irq.h> 19 19 #include <linux/of_platform.h> 20 + #include <linux/syscore_ops.h> 20 21 21 22 #define EIOINTC_REG_NODEMAP 0x14a0 22 23 #define EIOINTC_REG_IPMAP 0x14c0 ··· 302 301 return NULL; 303 302 } 304 303 305 - static int __init 306 - pch_pic_parse_madt(union acpi_subtable_headers *header, 307 - const unsigned long end) 304 + static int eiointc_suspend(void) 305 + { 306 + return 0; 307 + } 308 + 309 + static void eiointc_resume(void) 310 + { 311 + int i, j; 312 + struct irq_desc *desc; 313 + struct irq_data *irq_data; 314 + 315 + eiointc_router_init(0); 316 + 317 + for (i = 0; i < nr_pics; i++) { 318 + for (j = 0; j < VEC_COUNT; j++) { 319 + desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j); 320 + if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) { 321 + raw_spin_lock(&desc->lock); 322 + irq_data = &desc->irq_data; 323 + eiointc_set_irq_affinity(irq_data, irq_data->common->affinity, 0); 324 + raw_spin_unlock(&desc->lock); 325 + } 326 + } 327 + } 328 + } 329 + 330 + static struct syscore_ops eiointc_syscore_ops = { 331 + .suspend = eiointc_suspend, 332 + .resume = eiointc_resume, 333 + }; 334 + 335 + static int __init pch_pic_parse_madt(union acpi_subtable_headers *header, 336 + const unsigned long end) 308 337 { 309 338 struct acpi_madt_bio_pic *pchpic_entry = (struct acpi_madt_bio_pic *)header; 310 339 unsigned int node = (pchpic_entry->address >> 44) & 0xf; ··· 346 315 return -EINVAL; 347 316 } 348 317 349 - static int __init 350 - pch_msi_parse_madt(union acpi_subtable_headers *header, 351 - const unsigned long end) 318 + static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, 319 + const unsigned long end) 352 320 { 353 321 struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header; 354 322 struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group); ··· 360 330 361 331 static int __init acpi_cascade_irqdomain_init(void) 362 332 { 363 - acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, 364 - pch_pic_parse_madt, 0); 365 - acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, 366 - pch_msi_parse_madt, 1); 333 + int r; 334 + 335 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, pch_pic_parse_madt, 0); 336 + if (r < 0) 337 + return r; 338 + 339 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, pch_msi_parse_madt, 1); 340 + if (r < 0) 341 + return r; 342 + 367 343 return 0; 368 344 } 369 345 370 346 int __init eiointc_acpi_init(struct irq_domain *parent, 371 347 struct acpi_madt_eio_pic *acpi_eiointc) 372 348 { 373 - int i, parent_irq; 349 + int i, ret, parent_irq; 374 350 unsigned long node_map; 375 351 struct eiointc_priv *priv; 376 352 ··· 416 380 parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); 417 381 irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); 418 382 383 + register_syscore_ops(&eiointc_syscore_ops); 419 384 cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, 420 385 "irqchip/loongarch/intc:starting", 421 386 eiointc_router_init, NULL); 422 387 423 388 acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); 424 389 acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); 425 - acpi_cascade_irqdomain_init(); 390 + ret = acpi_cascade_irqdomain_init(); 426 391 427 - return 0; 392 + return ret; 428 393 429 394 out_free_handle: 430 395 irq_domain_free_fwnode(priv->domain_handle);
+147 -39
drivers/irqchip/irq-loongson-htvec.c
··· 16 16 #include <linux/of_address.h> 17 17 #include <linux/of_irq.h> 18 18 #include <linux/of_platform.h> 19 + #include <linux/syscore_ops.h> 19 20 20 21 /* Registers */ 21 22 #define HTVEC_EN_OFF 0x20 22 23 #define HTVEC_MAX_PARENT_IRQ 8 23 - 24 24 #define VEC_COUNT_PER_REG 32 25 25 #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) 26 26 #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) ··· 30 30 void __iomem *base; 31 31 struct irq_domain *htvec_domain; 32 32 raw_spinlock_t htvec_lock; 33 + u32 saved_vec_en[HTVEC_MAX_PARENT_IRQ]; 33 34 }; 35 + 36 + static struct htvec *htvec_priv; 34 37 35 38 static void htvec_irq_dispatch(struct irq_desc *desc) 36 39 { ··· 158 155 } 159 156 } 160 157 161 - static int htvec_of_init(struct device_node *node, 162 - struct device_node *parent) 158 + static int htvec_suspend(void) 163 159 { 160 + int i; 161 + 162 + for (i = 0; i < htvec_priv->num_parents; i++) 163 + htvec_priv->saved_vec_en[i] = readl(htvec_priv->base + HTVEC_EN_OFF + 4 * i); 164 + 165 + return 0; 166 + } 167 + 168 + static void htvec_resume(void) 169 + { 170 + int i; 171 + 172 + for (i = 0; i < htvec_priv->num_parents; i++) 173 + writel(htvec_priv->saved_vec_en[i], htvec_priv->base + HTVEC_EN_OFF + 4 * i); 174 + } 175 + 176 + static struct syscore_ops htvec_syscore_ops = { 177 + .suspend = htvec_suspend, 178 + .resume = htvec_resume, 179 + }; 180 + 181 + static int htvec_init(phys_addr_t addr, unsigned long size, 182 + int num_parents, int parent_irq[], struct fwnode_handle *domain_handle) 183 + { 184 + int i; 164 185 struct htvec *priv; 165 - int err, parent_irq[8], i; 166 186 167 187 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 168 188 if (!priv) 169 189 return -ENOMEM; 170 190 191 + priv->num_parents = num_parents; 192 + priv->base = ioremap(addr, size); 171 193 raw_spin_lock_init(&priv->htvec_lock); 172 - priv->base = of_iomap(node, 0); 173 - if (!priv->base) { 174 - err = -ENOMEM; 175 - goto free_priv; 194 + 195 + /* Setup IRQ domain */ 196 + priv->htvec_domain = irq_domain_create_linear(domain_handle, 197 + (VEC_COUNT_PER_REG * priv->num_parents), 198 + &htvec_domain_ops, priv); 199 + if (!priv->htvec_domain) { 200 + pr_err("loongson-htvec: cannot add IRQ domain\n"); 201 + goto iounmap_base; 176 202 } 203 + 204 + htvec_reset(priv); 205 + 206 + for (i = 0; i < priv->num_parents; i++) { 207 + irq_set_chained_handler_and_data(parent_irq[i], 208 + htvec_irq_dispatch, priv); 209 + } 210 + 211 + htvec_priv = priv; 212 + 213 + register_syscore_ops(&htvec_syscore_ops); 214 + 215 + return 0; 216 + 217 + iounmap_base: 218 + iounmap(priv->base); 219 + kfree(priv); 220 + 221 + return -EINVAL; 222 + } 223 + 224 + #ifdef CONFIG_OF 225 + 226 + static int htvec_of_init(struct device_node *node, 227 + struct device_node *parent) 228 + { 229 + int i, err; 230 + int parent_irq[8]; 231 + int num_parents = 0; 232 + struct resource res; 233 + 234 + if (of_address_to_resource(node, 0, &res)) 235 + return -EINVAL; 177 236 178 237 /* Interrupt may come from any of the 8 interrupt lines */ 179 238 for (i = 0; i < HTVEC_MAX_PARENT_IRQ; i++) { ··· 243 178 if (parent_irq[i] <= 0) 244 179 break; 245 180 246 - priv->num_parents++; 181 + num_parents++; 247 182 } 248 183 249 - if (!priv->num_parents) { 250 - pr_err("Failed to get parent irqs\n"); 251 - err = -ENODEV; 252 - goto iounmap_base; 253 - } 254 - 255 - priv->htvec_domain = irq_domain_create_linear(of_node_to_fwnode(node), 256 - (VEC_COUNT_PER_REG * priv->num_parents), 257 - &htvec_domain_ops, priv); 258 - if (!priv->htvec_domain) { 259 - pr_err("Failed to create IRQ domain\n"); 260 - err = -ENOMEM; 261 - goto irq_dispose; 262 - } 263 - 264 - htvec_reset(priv); 265 - 266 - for (i = 0; i < priv->num_parents; i++) 267 - irq_set_chained_handler_and_data(parent_irq[i], 268 - htvec_irq_dispatch, priv); 184 + err = htvec_init(res.start, resource_size(&res), 185 + num_parents, parent_irq, of_node_to_fwnode(node)); 186 + if (err < 0) 187 + return err; 269 188 270 189 return 0; 271 - 272 - irq_dispose: 273 - for (; i > 0; i--) 274 - irq_dispose_mapping(parent_irq[i - 1]); 275 - iounmap_base: 276 - iounmap(priv->base); 277 - free_priv: 278 - kfree(priv); 279 - 280 - return err; 281 190 } 282 191 283 192 IRQCHIP_DECLARE(htvec, "loongson,htvec-1.0", htvec_of_init); 193 + 194 + #endif 195 + 196 + #ifdef CONFIG_ACPI 197 + static int __init pch_pic_parse_madt(union acpi_subtable_headers *header, 198 + const unsigned long end) 199 + { 200 + struct acpi_madt_bio_pic *pchpic_entry = (struct acpi_madt_bio_pic *)header; 201 + 202 + return pch_pic_acpi_init(htvec_priv->htvec_domain, pchpic_entry); 203 + } 204 + 205 + static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, 206 + const unsigned long end) 207 + { 208 + struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header; 209 + 210 + return pch_msi_acpi_init(htvec_priv->htvec_domain, pchmsi_entry); 211 + } 212 + 213 + static int __init acpi_cascade_irqdomain_init(void) 214 + { 215 + int r; 216 + 217 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, pch_pic_parse_madt, 0); 218 + if (r < 0) 219 + return r; 220 + 221 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, pch_msi_parse_madt, 0); 222 + if (r < 0) 223 + return r; 224 + 225 + return 0; 226 + } 227 + 228 + int __init htvec_acpi_init(struct irq_domain *parent, 229 + struct acpi_madt_ht_pic *acpi_htvec) 230 + { 231 + int i, ret; 232 + int num_parents, parent_irq[8]; 233 + struct fwnode_handle *domain_handle; 234 + 235 + if (!acpi_htvec) 236 + return -EINVAL; 237 + 238 + num_parents = HTVEC_MAX_PARENT_IRQ; 239 + 240 + domain_handle = irq_domain_alloc_fwnode(&acpi_htvec->address); 241 + if (!domain_handle) { 242 + pr_err("Unable to allocate domain handle\n"); 243 + return -ENOMEM; 244 + } 245 + 246 + /* Interrupt may come from any of the 8 interrupt lines */ 247 + for (i = 0; i < HTVEC_MAX_PARENT_IRQ; i++) 248 + parent_irq[i] = irq_create_mapping(parent, acpi_htvec->cascade[i]); 249 + 250 + ret = htvec_init(acpi_htvec->address, acpi_htvec->size, 251 + num_parents, parent_irq, domain_handle); 252 + 253 + if (ret == 0) 254 + ret = acpi_cascade_irqdomain_init(); 255 + else 256 + irq_domain_free_fwnode(domain_handle); 257 + 258 + return ret; 259 + } 260 + 261 + #endif
+34 -3
drivers/irqchip/irq-loongson-liointc.c
··· 167 167 if (WARN_ON(intsize < 1)) 168 168 return -EINVAL; 169 169 *out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ; 170 - *out_type = IRQ_TYPE_NONE; 170 + 171 + if (intsize > 1) 172 + *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; 173 + else 174 + *out_type = IRQ_TYPE_NONE; 175 + 171 176 return 0; 172 177 } 173 178 ··· 212 207 "reg-names", core_reg_names[i]); 213 208 214 209 if (index < 0) 215 - goto out_iounmap; 210 + continue; 216 211 217 212 priv->core_isr[i] = of_iomap(node, index); 218 213 } 214 + 215 + if (!priv->core_isr[0]) 216 + goto out_iounmap; 219 217 } 220 218 221 219 /* Setup IRQ domain */ ··· 357 349 #endif 358 350 359 351 #ifdef CONFIG_ACPI 352 + static int __init htintc_parse_madt(union acpi_subtable_headers *header, 353 + const unsigned long end) 354 + { 355 + struct acpi_madt_ht_pic *htintc_entry = (struct acpi_madt_ht_pic *)header; 356 + struct irq_domain *parent = irq_find_matching_fwnode(liointc_handle, DOMAIN_BUS_ANY); 357 + 358 + return htvec_acpi_init(parent, htintc_entry); 359 + } 360 + 361 + static int __init acpi_cascade_irqdomain_init(void) 362 + { 363 + int r; 364 + 365 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_HT_PIC, htintc_parse_madt, 0); 366 + if (r < 0) 367 + return r; 368 + 369 + return 0; 370 + } 371 + 360 372 int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc) 361 373 { 362 374 int ret; ··· 393 365 pr_err("Unable to allocate domain handle\n"); 394 366 return -ENOMEM; 395 367 } 368 + 396 369 ret = liointc_init(acpi_liointc->address, acpi_liointc->size, 397 370 1, domain_handle, NULL); 398 - if (ret) 371 + if (ret == 0) 372 + ret = acpi_cascade_irqdomain_init(); 373 + else 399 374 irq_domain_free_fwnode(domain_handle); 400 375 401 376 return ret;
+25
drivers/irqchip/irq-loongson-pch-lpc.c
··· 13 13 #include <linux/irqchip/chained_irq.h> 14 14 #include <linux/irqdomain.h> 15 15 #include <linux/kernel.h> 16 + #include <linux/syscore_ops.h> 16 17 17 18 /* Registers */ 18 19 #define LPC_INT_CTL 0x00 ··· 35 34 u32 saved_reg_pol; 36 35 }; 37 36 37 + static struct pch_lpc *pch_lpc_priv; 38 38 struct fwnode_handle *pch_lpc_handle; 39 39 40 40 static void lpc_irq_ack(struct irq_data *d) ··· 149 147 (readl(priv->base + LPC_INT_STS) == 0xffffffff); 150 148 } 151 149 150 + static int pch_lpc_suspend(void) 151 + { 152 + pch_lpc_priv->saved_reg_ctl = readl(pch_lpc_priv->base + LPC_INT_CTL); 153 + pch_lpc_priv->saved_reg_ena = readl(pch_lpc_priv->base + LPC_INT_ENA); 154 + pch_lpc_priv->saved_reg_pol = readl(pch_lpc_priv->base + LPC_INT_POL); 155 + return 0; 156 + } 157 + 158 + static void pch_lpc_resume(void) 159 + { 160 + writel(pch_lpc_priv->saved_reg_ctl, pch_lpc_priv->base + LPC_INT_CTL); 161 + writel(pch_lpc_priv->saved_reg_ena, pch_lpc_priv->base + LPC_INT_ENA); 162 + writel(pch_lpc_priv->saved_reg_pol, pch_lpc_priv->base + LPC_INT_POL); 163 + } 164 + 165 + static struct syscore_ops pch_lpc_syscore_ops = { 166 + .suspend = pch_lpc_suspend, 167 + .resume = pch_lpc_resume, 168 + }; 169 + 152 170 int __init pch_lpc_acpi_init(struct irq_domain *parent, 153 171 struct acpi_madt_lpc_pic *acpi_pchlpc) 154 172 { ··· 213 191 parent_irq = irq_create_fwspec_mapping(&fwspec); 214 192 irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv); 215 193 194 + pch_lpc_priv = priv; 216 195 pch_lpc_handle = irq_handle; 196 + register_syscore_ops(&pch_lpc_syscore_ops); 197 + 217 198 return 0; 218 199 219 200 free_irq_handle:
+66 -10
drivers/irqchip/irq-loongson-pch-pic.c
··· 15 15 #include <linux/of_address.h> 16 16 #include <linux/of_irq.h> 17 17 #include <linux/of_platform.h> 18 + #include <linux/syscore_ops.h> 18 19 19 20 /* Registers */ 20 21 #define PCH_PIC_MASK 0x20 ··· 43 42 raw_spinlock_t pic_lock; 44 43 u32 vec_count; 45 44 u32 gsi_base; 45 + u32 saved_vec_en[PIC_REG_COUNT]; 46 + u32 saved_vec_pol[PIC_REG_COUNT]; 47 + u32 saved_vec_edge[PIC_REG_COUNT]; 46 48 }; 47 49 48 50 static struct pch_pic *pch_pic_priv[MAX_IO_PICS]; ··· 149 145 .irq_ack = pch_pic_ack_irq, 150 146 .irq_set_affinity = irq_chip_set_affinity_parent, 151 147 .irq_set_type = pch_pic_set_type, 148 + .flags = IRQCHIP_SKIP_SET_WAKE, 152 149 }; 153 150 154 151 static int pch_pic_domain_translate(struct irq_domain *d, ··· 160 155 struct pch_pic *priv = d->host_data; 161 156 struct device_node *of_node = to_of_node(fwspec->fwnode); 162 157 163 - if (fwspec->param_count < 1) 164 - return -EINVAL; 165 - 166 158 if (of_node) { 159 + if (fwspec->param_count < 2) 160 + return -EINVAL; 161 + 167 162 *hwirq = fwspec->param[0] + priv->ht_vec_base; 168 163 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 169 164 } else { 165 + if (fwspec->param_count < 1) 166 + return -EINVAL; 167 + 170 168 *hwirq = fwspec->param[0] - priv->gsi_base; 171 - *type = IRQ_TYPE_NONE; 169 + if (fwspec->param_count > 1) 170 + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 171 + else 172 + *type = IRQ_TYPE_NONE; 172 173 } 173 174 174 175 return 0; ··· 239 228 } 240 229 } 241 230 231 + static int pch_pic_suspend(void) 232 + { 233 + int i, j; 234 + 235 + for (i = 0; i < nr_pics; i++) { 236 + for (j = 0; j < PIC_REG_COUNT; j++) { 237 + pch_pic_priv[i]->saved_vec_pol[j] = 238 + readl(pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j); 239 + pch_pic_priv[i]->saved_vec_edge[j] = 240 + readl(pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j); 241 + pch_pic_priv[i]->saved_vec_en[j] = 242 + readl(pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j); 243 + } 244 + } 245 + 246 + return 0; 247 + } 248 + 249 + static void pch_pic_resume(void) 250 + { 251 + int i, j; 252 + 253 + for (i = 0; i < nr_pics; i++) { 254 + pch_pic_reset(pch_pic_priv[i]); 255 + for (j = 0; j < PIC_REG_COUNT; j++) { 256 + writel(pch_pic_priv[i]->saved_vec_pol[j], 257 + pch_pic_priv[i]->base + PCH_PIC_POL + 4 * j); 258 + writel(pch_pic_priv[i]->saved_vec_edge[j], 259 + pch_pic_priv[i]->base + PCH_PIC_EDGE + 4 * j); 260 + writel(pch_pic_priv[i]->saved_vec_en[j], 261 + pch_pic_priv[i]->base + PCH_PIC_MASK + 4 * j); 262 + } 263 + } 264 + } 265 + 266 + static struct syscore_ops pch_pic_syscore_ops = { 267 + .suspend = pch_pic_suspend, 268 + .resume = pch_pic_resume, 269 + }; 270 + 242 271 static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base, 243 272 struct irq_domain *parent_domain, struct fwnode_handle *domain_handle, 244 273 u32 gsi_base) ··· 310 259 pch_pic_reset(priv); 311 260 pch_pic_handle[nr_pics] = domain_handle; 312 261 pch_pic_priv[nr_pics++] = priv; 262 + 263 + register_syscore_ops(&pch_pic_syscore_ops); 313 264 314 265 return 0; 315 266 ··· 378 325 return -1; 379 326 } 380 327 381 - static int __init 382 - pch_lpc_parse_madt(union acpi_subtable_headers *header, 383 - const unsigned long end) 328 + static int __init pch_lpc_parse_madt(union acpi_subtable_headers *header, 329 + const unsigned long end) 384 330 { 385 331 struct acpi_madt_lpc_pic *pchlpc_entry = (struct acpi_madt_lpc_pic *)header; 386 332 ··· 388 336 389 337 static int __init acpi_cascade_irqdomain_init(void) 390 338 { 391 - acpi_table_parse_madt(ACPI_MADT_TYPE_LPC_PIC, 392 - pch_lpc_parse_madt, 0); 339 + int r; 340 + 341 + r = acpi_table_parse_madt(ACPI_MADT_TYPE_LPC_PIC, pch_lpc_parse_madt, 0); 342 + if (r < 0) 343 + return r; 344 + 393 345 return 0; 394 346 } 395 347 ··· 420 364 } 421 365 422 366 if (acpi_pchpic->id == 0) 423 - acpi_cascade_irqdomain_init(); 367 + ret = acpi_cascade_irqdomain_init(); 424 368 425 369 return ret; 426 370 }
+1 -1
drivers/irqchip/irq-ls-extirq.c
··· 203 203 if (ret) 204 204 goto err_parse_map; 205 205 206 - priv->big_endian = of_device_is_big_endian(parent); 206 + priv->big_endian = of_device_is_big_endian(node->parent); 207 207 priv->is_ls1021a_or_ls1043a = of_device_is_compatible(node, "fsl,ls1021a-extirq") || 208 208 of_device_is_compatible(node, "fsl,ls1043a-extirq"); 209 209 raw_spin_lock_init(&priv->lock);
+1 -1
drivers/irqchip/irq-mips-gic.c
··· 494 494 map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin; 495 495 496 496 /* 497 - * If adding support for more per-cpu interrupts, keep the the 497 + * If adding support for more per-cpu interrupts, keep the 498 498 * array in gic_all_vpes_irq_cpu_online() in sync. 499 499 */ 500 500 switch (intr) {
+78 -17
drivers/irqchip/irq-mtk-cirq.c
··· 15 15 #include <linux/slab.h> 16 16 #include <linux/syscore_ops.h> 17 17 18 - #define CIRQ_ACK 0x40 19 - #define CIRQ_MASK_SET 0xc0 20 - #define CIRQ_MASK_CLR 0x100 21 - #define CIRQ_SENS_SET 0x180 22 - #define CIRQ_SENS_CLR 0x1c0 23 - #define CIRQ_POL_SET 0x240 24 - #define CIRQ_POL_CLR 0x280 25 - #define CIRQ_CONTROL 0x300 18 + enum mtk_cirq_regoffs_index { 19 + CIRQ_STA, 20 + CIRQ_ACK, 21 + CIRQ_MASK_SET, 22 + CIRQ_MASK_CLR, 23 + CIRQ_SENS_SET, 24 + CIRQ_SENS_CLR, 25 + CIRQ_POL_SET, 26 + CIRQ_POL_CLR, 27 + CIRQ_CONTROL 28 + }; 29 + 30 + static const u32 mtk_cirq_regoffs_v1[] = { 31 + [CIRQ_STA] = 0x0, 32 + [CIRQ_ACK] = 0x40, 33 + [CIRQ_MASK_SET] = 0xc0, 34 + [CIRQ_MASK_CLR] = 0x100, 35 + [CIRQ_SENS_SET] = 0x180, 36 + [CIRQ_SENS_CLR] = 0x1c0, 37 + [CIRQ_POL_SET] = 0x240, 38 + [CIRQ_POL_CLR] = 0x280, 39 + [CIRQ_CONTROL] = 0x300, 40 + }; 41 + 42 + static const u32 mtk_cirq_regoffs_v2[] = { 43 + [CIRQ_STA] = 0x0, 44 + [CIRQ_ACK] = 0x80, 45 + [CIRQ_MASK_SET] = 0x180, 46 + [CIRQ_MASK_CLR] = 0x200, 47 + [CIRQ_SENS_SET] = 0x300, 48 + [CIRQ_SENS_CLR] = 0x380, 49 + [CIRQ_POL_SET] = 0x480, 50 + [CIRQ_POL_CLR] = 0x500, 51 + [CIRQ_CONTROL] = 0x600, 52 + }; 26 53 27 54 #define CIRQ_EN 0x1 28 55 #define CIRQ_EDGE 0x2 ··· 59 32 void __iomem *base; 60 33 unsigned int ext_irq_start; 61 34 unsigned int ext_irq_end; 35 + const u32 *offsets; 62 36 struct irq_domain *domain; 63 37 }; 64 38 65 39 static struct mtk_cirq_chip_data *cirq_data; 66 40 67 - static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset) 41 + static void __iomem *mtk_cirq_reg(struct mtk_cirq_chip_data *chip_data, 42 + enum mtk_cirq_regoffs_index idx) 43 + { 44 + return chip_data->base + chip_data->offsets[idx]; 45 + } 46 + 47 + static void __iomem *mtk_cirq_irq_reg(struct mtk_cirq_chip_data *chip_data, 48 + enum mtk_cirq_regoffs_index idx, 49 + unsigned int cirq_num) 50 + { 51 + return mtk_cirq_reg(chip_data, idx) + (cirq_num / 32) * 4; 52 + } 53 + 54 + static void mtk_cirq_write_mask(struct irq_data *data, enum mtk_cirq_regoffs_index idx) 68 55 { 69 56 struct mtk_cirq_chip_data *chip_data = data->chip_data; 70 57 unsigned int cirq_num = data->hwirq; 71 58 u32 mask = 1 << (cirq_num % 32); 72 59 73 - writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4); 60 + writel_relaxed(mask, mtk_cirq_irq_reg(chip_data, idx, cirq_num)); 74 61 } 75 62 76 63 static void mtk_cirq_mask(struct irq_data *data) ··· 201 160 #ifdef CONFIG_PM_SLEEP 202 161 static int mtk_cirq_suspend(void) 203 162 { 163 + void __iomem *reg; 204 164 u32 value, mask; 205 165 unsigned int irq, hwirq_num; 206 166 bool pending, masked; ··· 242 200 continue; 243 201 } 244 202 203 + reg = mtk_cirq_irq_reg(cirq_data, CIRQ_ACK, i); 245 204 mask = 1 << (i % 32); 246 - writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4); 205 + writel_relaxed(mask, reg); 247 206 } 248 207 249 208 /* set edge_only mode, record edge-triggerd interrupts */ 250 209 /* enable cirq */ 251 - value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 210 + reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL); 211 + value = readl_relaxed(reg); 252 212 value |= (CIRQ_EDGE | CIRQ_EN); 253 - writel_relaxed(value, cirq_data->base + CIRQ_CONTROL); 213 + writel_relaxed(value, reg); 254 214 255 215 return 0; 256 216 } 257 217 258 218 static void mtk_cirq_resume(void) 259 219 { 220 + void __iomem *reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL); 260 221 u32 value; 261 222 262 223 /* flush recorded interrupts, will send signals to parent controller */ 263 - value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 264 - writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL); 224 + value = readl_relaxed(reg); 225 + writel_relaxed(value | CIRQ_FLUSH, reg); 265 226 266 227 /* disable cirq */ 267 - value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 228 + value = readl_relaxed(reg); 268 229 value &= ~(CIRQ_EDGE | CIRQ_EN); 269 - writel_relaxed(value, cirq_data->base + CIRQ_CONTROL); 230 + writel_relaxed(value, reg); 270 231 } 271 232 272 233 static struct syscore_ops mtk_cirq_syscore_ops = { ··· 285 240 static inline void mtk_cirq_syscore_init(void) {} 286 241 #endif 287 242 243 + static const struct of_device_id mtk_cirq_of_match[] = { 244 + { .compatible = "mediatek,mt2701-cirq", .data = &mtk_cirq_regoffs_v1 }, 245 + { .compatible = "mediatek,mt8135-cirq", .data = &mtk_cirq_regoffs_v1 }, 246 + { .compatible = "mediatek,mt8173-cirq", .data = &mtk_cirq_regoffs_v1 }, 247 + { .compatible = "mediatek,mt8192-cirq", .data = &mtk_cirq_regoffs_v2 }, 248 + { /* sentinel */ } 249 + }; 250 + 288 251 static int __init mtk_cirq_of_init(struct device_node *node, 289 252 struct device_node *parent) 290 253 { 291 254 struct irq_domain *domain, *domain_parent; 255 + const struct of_device_id *match; 292 256 unsigned int irq_num; 293 257 int ret; 294 258 ··· 327 273 &cirq_data->ext_irq_end); 328 274 if (ret) 329 275 goto out_unmap; 276 + 277 + match = of_match_node(mtk_cirq_of_match, node); 278 + if (!match) { 279 + ret = -ENODEV; 280 + goto out_unmap; 281 + } 282 + cirq_data->offsets = match->data; 330 283 331 284 irq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1; 332 285 domain = irq_domain_add_hierarchy(domain_parent, 0,
+2 -2
drivers/irqchip/irq-mvebu-icu.c
··· 151 151 mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, 152 152 unsigned long *hwirq, unsigned int *type) 153 153 { 154 - struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d); 155 - struct mvebu_icu *icu = platform_msi_get_host_data(d); 156 154 unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2; 155 + struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d); 156 + struct mvebu_icu *icu = msi_data->icu; 157 157 158 158 /* Check the count of the parameters in dt */ 159 159 if (WARN_ON(fwspec->param_count != param_count)) {
+4 -2
drivers/irqchip/irq-sifive-plic.c
··· 187 187 .irq_set_affinity = plic_set_affinity, 188 188 #endif 189 189 .irq_set_type = plic_irq_set_type, 190 - .flags = IRQCHIP_AFFINITY_PRE_STARTUP, 190 + .flags = IRQCHIP_SKIP_SET_WAKE | 191 + IRQCHIP_AFFINITY_PRE_STARTUP, 191 192 }; 192 193 193 194 static struct irq_chip plic_chip = { ··· 202 201 .irq_set_affinity = plic_set_affinity, 203 202 #endif 204 203 .irq_set_type = plic_irq_set_type, 205 - .flags = IRQCHIP_AFFINITY_PRE_STARTUP, 204 + .flags = IRQCHIP_SKIP_SET_WAKE | 205 + IRQCHIP_AFFINITY_PRE_STARTUP, 206 206 }; 207 207 208 208 static int plic_irq_set_type(struct irq_data *d, unsigned int type)
+1 -2
drivers/irqchip/irq-sl28cpld.c
··· 65 65 irqchip->chip.num_irqs = ARRAY_SIZE(sl28cpld_irqs); 66 66 irqchip->chip.num_regs = 1; 67 67 irqchip->chip.status_base = base + INTC_IP; 68 - irqchip->chip.mask_base = base + INTC_IE; 69 - irqchip->chip.mask_invert = true; 68 + irqchip->chip.unmask_base = base + INTC_IE; 70 69 irqchip->chip.ack_base = base + INTC_IP; 71 70 72 71 return devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev),
+1 -6
drivers/irqchip/irq-st.c
··· 153 153 static int st_irq_syscfg_probe(struct platform_device *pdev) 154 154 { 155 155 struct device_node *np = pdev->dev.of_node; 156 - const struct of_device_id *match; 157 156 struct st_irq_syscfg *ddata; 158 157 159 158 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); 160 159 if (!ddata) 161 160 return -ENOMEM; 162 161 163 - match = of_match_device(st_irq_syscfg_match, &pdev->dev); 164 - if (!match) 165 - return -ENODEV; 166 - 167 - ddata->syscfg = (unsigned int)match->data; 162 + ddata->syscfg = (unsigned int) device_get_match_data(&pdev->dev); 168 163 169 164 ddata->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); 170 165 if (IS_ERR(ddata->regmap)) {
+1 -1
drivers/irqchip/irq-ti-sci-inta.c
··· 168 168 /** 169 169 * ti_sci_inta_xlate_irq() - Translate hwirq to parent's hwirq. 170 170 * @inta: IRQ domain corresponding to Interrupt Aggregator 171 - * @irq: Hardware irq corresponding to the above irq domain 171 + * @vint_id: Hardware irq corresponding to the above irq domain 172 172 * 173 173 * Return parent irq number if translation is available else -ENOENT. 174 174 */
+1
drivers/irqchip/irq-wpcm450-aic.c
··· 146 146 aic->regs = of_iomap(node, 0); 147 147 if (!aic->regs) { 148 148 pr_err("Failed to map WPCM450 AIC registers\n"); 149 + kfree(aic); 149 150 return -ENOMEM; 150 151 } 151 152
+1 -1
drivers/mailbox/Kconfig
··· 223 223 tristate "Broadcom FlexRM Mailbox" 224 224 depends on ARM64 225 225 depends on ARCH_BCM_IPROC || COMPILE_TEST 226 - select GENERIC_MSI_IRQ_DOMAIN 226 + select GENERIC_MSI_IRQ 227 227 default m if ARCH_BCM_IPROC 228 228 help 229 229 Mailbox implementation of the Broadcom FlexRM ring manager,
+1 -6
drivers/pci/Kconfig
··· 51 51 52 52 If you don't know what to do here, say Y. 53 53 54 - config PCI_MSI_IRQ_DOMAIN 55 - def_bool y 56 - depends on PCI_MSI 57 - select GENERIC_MSI_IRQ_DOMAIN 58 - 59 54 config PCI_MSI_ARCH_FALLBACKS 60 55 bool 61 56 ··· 187 192 188 193 config PCI_HYPERV 189 194 tristate "Hyper-V PCI Frontend" 190 - depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && SYSFS 195 + depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && SYSFS 191 196 select PCI_HYPERV_INTERFACE 192 197 help 193 198 The PCI device frontend driver allows the kernel to import arbitrary
+14 -16
drivers/pci/controller/Kconfig
··· 19 19 tristate "Aardvark PCIe controller" 20 20 depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST 21 21 depends on OF 22 - depends on PCI_MSI_IRQ_DOMAIN 22 + depends on PCI_MSI 23 23 select PCI_BRIDGE_EMUL 24 24 help 25 25 Add support for Aardvark 64bit PCIe Host Controller. This ··· 29 29 config PCIE_XILINX_NWL 30 30 bool "NWL PCIe Core" 31 31 depends on ARCH_ZYNQMP || COMPILE_TEST 32 - depends on PCI_MSI_IRQ_DOMAIN 32 + depends on PCI_MSI 33 33 help 34 34 Say 'Y' here if you want kernel support for Xilinx 35 35 NWL PCIe controller. The controller can act as Root Port ··· 53 53 config PCI_TEGRA 54 54 bool "NVIDIA Tegra PCIe controller" 55 55 depends on ARCH_TEGRA || COMPILE_TEST 56 - depends on PCI_MSI_IRQ_DOMAIN 56 + depends on PCI_MSI 57 57 help 58 58 Say Y here if you want support for the PCIe host controller found 59 59 on NVIDIA Tegra SoCs. ··· 70 70 config PCIE_RCAR_HOST 71 71 bool "Renesas R-Car PCIe host controller" 72 72 depends on ARCH_RENESAS || COMPILE_TEST 73 - depends on PCI_MSI_IRQ_DOMAIN 73 + depends on PCI_MSI 74 74 help 75 75 Say Y here if you want PCIe controller support on R-Car SoCs in host 76 76 mode. ··· 99 99 config PCIE_XILINX 100 100 bool "Xilinx AXI PCIe host bridge support" 101 101 depends on OF || COMPILE_TEST 102 - depends on PCI_MSI_IRQ_DOMAIN 102 + depends on PCI_MSI 103 103 help 104 104 Say 'Y' here if you want kernel to support the Xilinx AXI PCIe 105 105 Host Bridge driver. ··· 124 124 config PCI_XGENE_MSI 125 125 bool "X-Gene v1 PCIe MSI feature" 126 126 depends on PCI_XGENE 127 - depends on PCI_MSI_IRQ_DOMAIN 127 + depends on PCI_MSI 128 128 default y 129 129 help 130 130 Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC. ··· 170 170 config PCIE_IPROC_MSI 171 171 bool "Broadcom iProc PCIe MSI support" 172 172 depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA 173 - depends on PCI_MSI_IRQ_DOMAIN 173 + depends on PCI_MSI 174 174 default ARCH_BCM_IPROC 175 175 help 176 176 Say Y here if you want to enable MSI support for Broadcom's iProc ··· 186 186 config PCIE_ALTERA_MSI 187 187 tristate "Altera PCIe MSI feature" 188 188 depends on PCIE_ALTERA 189 - depends on PCI_MSI_IRQ_DOMAIN 189 + depends on PCI_MSI 190 190 help 191 191 Say Y here if you want PCIe MSI support for the Altera FPGA. 192 192 This MSI driver supports Altera MSI to GIC controller IP. ··· 215 215 tristate "Rockchip PCIe host controller" 216 216 depends on ARCH_ROCKCHIP || COMPILE_TEST 217 217 depends on OF 218 - depends on PCI_MSI_IRQ_DOMAIN 218 + depends on PCI_MSI 219 219 select MFD_SYSCON 220 220 select PCIE_ROCKCHIP 221 221 help ··· 239 239 tristate "MediaTek PCIe controller" 240 240 depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST 241 241 depends on OF 242 - depends on PCI_MSI_IRQ_DOMAIN 242 + depends on PCI_MSI 243 243 help 244 244 Say Y here if you want to enable PCIe controller support on 245 245 MediaTek SoCs. ··· 247 247 config PCIE_MEDIATEK_GEN3 248 248 tristate "MediaTek Gen3 PCIe controller" 249 249 depends on ARCH_MEDIATEK || COMPILE_TEST 250 - depends on PCI_MSI_IRQ_DOMAIN 250 + depends on PCI_MSI 251 251 help 252 252 Adds support for PCIe Gen3 MAC controller for MediaTek SoCs. 253 253 This PCIe controller is compatible with Gen3, Gen2 and Gen1 speed, ··· 277 277 depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCMBCA || \ 278 278 BMIPS_GENERIC || COMPILE_TEST 279 279 depends on OF 280 - depends on PCI_MSI_IRQ_DOMAIN 280 + depends on PCI_MSI 281 281 default ARCH_BRCMSTB || BMIPS_GENERIC 282 282 help 283 283 Say Y here to enable PCIe host controller support for ··· 285 285 286 286 config PCI_HYPERV_INTERFACE 287 287 tristate "Hyper-V PCI Interface" 288 - depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN 288 + depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && PCI_MSI 289 289 help 290 290 The Hyper-V PCI Interface is a helper driver allows other drivers to 291 291 have a common interface with the Hyper-V PCI frontend driver. ··· 303 303 config PCIE_MICROCHIP_HOST 304 304 bool "Microchip AXI PCIe host bridge support" 305 305 depends on PCI_MSI && OF 306 - select PCI_MSI_IRQ_DOMAIN 307 - select GENERIC_MSI_IRQ_DOMAIN 308 306 select PCI_HOST_COMMON 309 307 help 310 308 Say Y here if you want kernel to support the Microchip AXI PCIe ··· 324 326 tristate "Apple PCIe controller" 325 327 depends on ARCH_APPLE || COMPILE_TEST 326 328 depends on OF 327 - depends on PCI_MSI_IRQ_DOMAIN 329 + depends on PCI_MSI 328 330 select PCI_HOST_COMMON 329 331 help 330 332 Say Y here if you want to enable PCIe controller support on Apple
+24 -24
drivers/pci/controller/dwc/Kconfig
··· 21 21 tristate "TI DRA7xx PCIe controller Host Mode" 22 22 depends on SOC_DRA7XX || COMPILE_TEST 23 23 depends on OF && HAS_IOMEM && TI_PIPE3 24 - depends on PCI_MSI_IRQ_DOMAIN 24 + depends on PCI_MSI 25 25 select PCIE_DW_HOST 26 26 select PCI_DRA7XX 27 27 default y if SOC_DRA7XX ··· 53 53 54 54 config PCIE_DW_PLAT_HOST 55 55 bool "Platform bus based DesignWare PCIe Controller - Host mode" 56 - depends on PCI_MSI_IRQ_DOMAIN 56 + depends on PCI_MSI 57 57 select PCIE_DW_HOST 58 58 select PCIE_DW_PLAT 59 59 help ··· 67 67 68 68 config PCIE_DW_PLAT_EP 69 69 bool "Platform bus based DesignWare PCIe Controller - Endpoint mode" 70 - depends on PCI && PCI_MSI_IRQ_DOMAIN 70 + depends on PCI && PCI_MSI 71 71 depends on PCI_ENDPOINT 72 72 select PCIE_DW_EP 73 73 select PCIE_DW_PLAT ··· 83 83 config PCI_EXYNOS 84 84 tristate "Samsung Exynos PCIe controller" 85 85 depends on ARCH_EXYNOS || COMPILE_TEST 86 - depends on PCI_MSI_IRQ_DOMAIN 86 + depends on PCI_MSI 87 87 select PCIE_DW_HOST 88 88 help 89 89 Enables support for the PCIe controller in the Samsung Exynos SoCs ··· 94 94 config PCI_IMX6 95 95 bool "Freescale i.MX6/7/8 PCIe controller" 96 96 depends on ARCH_MXC || COMPILE_TEST 97 - depends on PCI_MSI_IRQ_DOMAIN 97 + depends on PCI_MSI 98 98 select PCIE_DW_HOST 99 99 100 100 config PCIE_SPEAR13XX 101 101 bool "STMicroelectronics SPEAr PCIe controller" 102 102 depends on ARCH_SPEAR13XX || COMPILE_TEST 103 - depends on PCI_MSI_IRQ_DOMAIN 103 + depends on PCI_MSI 104 104 select PCIE_DW_HOST 105 105 help 106 106 Say Y here if you want PCIe support on SPEAr13XX SoCs. ··· 111 111 config PCI_KEYSTONE_HOST 112 112 bool "PCI Keystone Host Mode" 113 113 depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST 114 - depends on PCI_MSI_IRQ_DOMAIN 114 + depends on PCI_MSI 115 115 select PCIE_DW_HOST 116 116 select PCI_KEYSTONE 117 117 help ··· 135 135 config PCI_LAYERSCAPE 136 136 bool "Freescale Layerscape PCIe controller - Host mode" 137 137 depends on OF && (ARM || ARCH_LAYERSCAPE || COMPILE_TEST) 138 - depends on PCI_MSI_IRQ_DOMAIN 138 + depends on PCI_MSI 139 139 select PCIE_DW_HOST 140 140 select MFD_SYSCON 141 141 help ··· 160 160 config PCI_HISI 161 161 depends on OF && (ARM64 || COMPILE_TEST) 162 162 bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers" 163 - depends on PCI_MSI_IRQ_DOMAIN 163 + depends on PCI_MSI 164 164 select PCIE_DW_HOST 165 165 select PCI_HOST_COMMON 166 166 help ··· 170 170 config PCIE_QCOM 171 171 bool "Qualcomm PCIe controller" 172 172 depends on OF && (ARCH_QCOM || COMPILE_TEST) 173 - depends on PCI_MSI_IRQ_DOMAIN 173 + depends on PCI_MSI 174 174 select PCIE_DW_HOST 175 175 select CRC8 176 176 help ··· 191 191 config PCIE_ARMADA_8K 192 192 bool "Marvell Armada-8K PCIe controller" 193 193 depends on ARCH_MVEBU || COMPILE_TEST 194 - depends on PCI_MSI_IRQ_DOMAIN 194 + depends on PCI_MSI 195 195 select PCIE_DW_HOST 196 196 help 197 197 Say Y here if you want to enable PCIe controller support on ··· 205 205 config PCIE_ARTPEC6_HOST 206 206 bool "Axis ARTPEC-6 PCIe controller Host Mode" 207 207 depends on MACH_ARTPEC6 || COMPILE_TEST 208 - depends on PCI_MSI_IRQ_DOMAIN 208 + depends on PCI_MSI 209 209 select PCIE_DW_HOST 210 210 select PCIE_ARTPEC6 211 211 help ··· 226 226 bool "Rockchip DesignWare PCIe controller" 227 227 select PCIE_DW 228 228 select PCIE_DW_HOST 229 - depends on PCI_MSI_IRQ_DOMAIN 229 + depends on PCI_MSI 230 230 depends on ARCH_ROCKCHIP || COMPILE_TEST 231 231 depends on OF 232 232 help ··· 236 236 config PCIE_INTEL_GW 237 237 bool "Intel Gateway PCIe host controller support" 238 238 depends on OF && (X86 || COMPILE_TEST) 239 - depends on PCI_MSI_IRQ_DOMAIN 239 + depends on PCI_MSI 240 240 select PCIE_DW_HOST 241 241 help 242 242 Say 'Y' here to enable PCIe Host controller support on Intel ··· 250 250 config PCIE_KEEMBAY_HOST 251 251 bool "Intel Keem Bay PCIe controller - Host mode" 252 252 depends on ARCH_KEEMBAY || COMPILE_TEST 253 - depends on PCI && PCI_MSI_IRQ_DOMAIN 253 + depends on PCI_MSI 254 254 select PCIE_DW_HOST 255 255 select PCIE_KEEMBAY 256 256 help ··· 262 262 config PCIE_KEEMBAY_EP 263 263 bool "Intel Keem Bay PCIe controller - Endpoint mode" 264 264 depends on ARCH_KEEMBAY || COMPILE_TEST 265 - depends on PCI && PCI_MSI_IRQ_DOMAIN 265 + depends on PCI_MSI 266 266 depends on PCI_ENDPOINT 267 267 select PCIE_DW_EP 268 268 select PCIE_KEEMBAY ··· 275 275 config PCIE_KIRIN 276 276 depends on OF && (ARM64 || COMPILE_TEST) 277 277 tristate "HiSilicon Kirin series SoCs PCIe controllers" 278 - depends on PCI_MSI_IRQ_DOMAIN 278 + depends on PCI_MSI 279 279 select PCIE_DW_HOST 280 280 help 281 281 Say Y here if you want PCIe controller support ··· 284 284 config PCIE_HISI_STB 285 285 bool "HiSilicon STB SoCs PCIe controllers" 286 286 depends on ARCH_HISI || COMPILE_TEST 287 - depends on PCI_MSI_IRQ_DOMAIN 287 + depends on PCI_MSI 288 288 select PCIE_DW_HOST 289 289 help 290 290 Say Y here if you want PCIe controller support on HiSilicon STB SoCs ··· 292 292 config PCI_MESON 293 293 tristate "MESON PCIe controller" 294 294 default m if ARCH_MESON 295 - depends on PCI_MSI_IRQ_DOMAIN 295 + depends on PCI_MSI 296 296 select PCIE_DW_HOST 297 297 help 298 298 Say Y here if you want to enable PCI controller support on Amlogic ··· 306 306 config PCIE_TEGRA194_HOST 307 307 tristate "NVIDIA Tegra194 (and later) PCIe controller - Host Mode" 308 308 depends on ARCH_TEGRA_194_SOC || COMPILE_TEST 309 - depends on PCI_MSI_IRQ_DOMAIN 309 + depends on PCI_MSI 310 310 select PCIE_DW_HOST 311 311 select PHY_TEGRA194_P2U 312 312 select PCIE_TEGRA194 ··· 336 336 config PCIE_VISCONTI_HOST 337 337 bool "Toshiba Visconti PCIe controllers" 338 338 depends on ARCH_VISCONTI || COMPILE_TEST 339 - depends on PCI_MSI_IRQ_DOMAIN 339 + depends on PCI_MSI 340 340 select PCIE_DW_HOST 341 341 help 342 342 Say Y here if you want PCIe controller support on Toshiba Visconti SoC. ··· 346 346 bool "Socionext UniPhier PCIe host controllers" 347 347 depends on ARCH_UNIPHIER || COMPILE_TEST 348 348 depends on OF && HAS_IOMEM 349 - depends on PCI_MSI_IRQ_DOMAIN 349 + depends on PCI_MSI 350 350 select PCIE_DW_HOST 351 351 help 352 352 Say Y here if you want PCIe host controller support on UniPhier SoCs. ··· 365 365 config PCIE_AL 366 366 bool "Amazon Annapurna Labs PCIe controller" 367 367 depends on OF && (ARM64 || COMPILE_TEST) 368 - depends on PCI_MSI_IRQ_DOMAIN 368 + depends on PCI_MSI 369 369 select PCIE_DW_HOST 370 370 select PCI_ECAM 371 371 help ··· 377 377 378 378 config PCIE_FU740 379 379 bool "SiFive FU740 PCIe host controller" 380 - depends on PCI_MSI_IRQ_DOMAIN 380 + depends on PCI_MSI 381 381 depends on SOC_SIFIVE || COMPILE_TEST 382 382 select PCIE_DW_HOST 383 383 help
+3 -3
drivers/pci/controller/mobiveil/Kconfig
··· 8 8 9 9 config PCIE_MOBIVEIL_HOST 10 10 bool 11 - depends on PCI_MSI_IRQ_DOMAIN 11 + depends on PCI_MSI 12 12 select PCIE_MOBIVEIL 13 13 14 14 config PCIE_MOBIVEIL_PLAT 15 15 bool "Mobiveil AXI PCIe controller" 16 16 depends on ARCH_ZYNQMP || COMPILE_TEST 17 17 depends on OF 18 - depends on PCI_MSI_IRQ_DOMAIN 18 + depends on PCI_MSI 19 19 select PCIE_MOBIVEIL_HOST 20 20 help 21 21 Say Y here if you want to enable support for the Mobiveil AXI PCIe ··· 25 25 config PCIE_LAYERSCAPE_GEN4 26 26 bool "Freescale Layerscape PCIe Gen4 controller" 27 27 depends on ARCH_LAYERSCAPE || COMPILE_TEST 28 - depends on PCI_MSI_IRQ_DOMAIN 28 + depends on PCI_MSI 29 29 select PCIE_MOBIVEIL_HOST 30 30 help 31 31 Say Y here if you want PCIe Gen4 controller support on
+1 -14
drivers/pci/controller/pci-hyperv.c
··· 611 611 return cfg->vector; 612 612 } 613 613 614 - static int hv_msi_prepare(struct irq_domain *domain, struct device *dev, 615 - int nvec, msi_alloc_info_t *info) 616 - { 617 - int ret = pci_msi_prepare(domain, dev, nvec, info); 618 - 619 - /* 620 - * By using the interrupt remapper in the hypervisor IOMMU, contiguous 621 - * CPU vectors is not needed for multi-MSI 622 - */ 623 - if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI) 624 - info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS; 625 - 626 - return ret; 627 - } 614 + #define hv_msi_prepare pci_msi_prepare 628 615 629 616 /** 630 617 * hv_arch_irq_unmask() - "Unmask" the IRQ by setting its current
+1 -2
drivers/pci/msi/Makefile
··· 2 2 # 3 3 # Makefile for the PCI/MSI 4 4 obj-$(CONFIG_PCI) += pcidev_msi.o 5 - obj-$(CONFIG_PCI_MSI) += msi.o 6 - obj-$(CONFIG_PCI_MSI_IRQ_DOMAIN) += irqdomain.o 5 + obj-$(CONFIG_PCI_MSI) += api.o msi.o irqdomain.o 7 6 obj-$(CONFIG_PCI_MSI_ARCH_FALLBACKS) += legacy.o
+458
drivers/pci/msi/api.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * PCI MSI/MSI-X — Exported APIs for device drivers 4 + * 5 + * Copyright (C) 2003-2004 Intel 6 + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) 7 + * Copyright (C) 2016 Christoph Hellwig. 8 + * Copyright (C) 2022 Linutronix GmbH 9 + */ 10 + 11 + #include <linux/export.h> 12 + #include <linux/irq.h> 13 + 14 + #include "msi.h" 15 + 16 + /** 17 + * pci_enable_msi() - Enable MSI interrupt mode on device 18 + * @dev: the PCI device to operate on 19 + * 20 + * Legacy device driver API to enable MSI interrupts mode on device and 21 + * allocate a single interrupt vector. On success, the allocated vector 22 + * Linux IRQ will be saved at @dev->irq. The driver must invoke 23 + * pci_disable_msi() on cleanup. 24 + * 25 + * NOTE: The newer pci_alloc_irq_vectors() / pci_free_irq_vectors() API 26 + * pair should, in general, be used instead. 27 + * 28 + * Return: 0 on success, errno otherwise 29 + */ 30 + int pci_enable_msi(struct pci_dev *dev) 31 + { 32 + int rc = __pci_enable_msi_range(dev, 1, 1, NULL); 33 + if (rc < 0) 34 + return rc; 35 + return 0; 36 + } 37 + EXPORT_SYMBOL(pci_enable_msi); 38 + 39 + /** 40 + * pci_disable_msi() - Disable MSI interrupt mode on device 41 + * @dev: the PCI device to operate on 42 + * 43 + * Legacy device driver API to disable MSI interrupt mode on device, 44 + * free earlier allocated interrupt vectors, and restore INTx emulation. 45 + * The PCI device Linux IRQ (@dev->irq) is restored to its default 46 + * pin-assertion IRQ. This is the cleanup pair of pci_enable_msi(). 47 + * 48 + * NOTE: The newer pci_alloc_irq_vectors() / pci_free_irq_vectors() API 49 + * pair should, in general, be used instead. 50 + */ 51 + void pci_disable_msi(struct pci_dev *dev) 52 + { 53 + if (!pci_msi_enabled() || !dev || !dev->msi_enabled) 54 + return; 55 + 56 + msi_lock_descs(&dev->dev); 57 + pci_msi_shutdown(dev); 58 + pci_free_msi_irqs(dev); 59 + msi_unlock_descs(&dev->dev); 60 + } 61 + EXPORT_SYMBOL(pci_disable_msi); 62 + 63 + /** 64 + * pci_msix_vec_count() - Get number of MSI-X interrupt vectors on device 65 + * @dev: the PCI device to operate on 66 + * 67 + * Return: number of MSI-X interrupt vectors available on this device 68 + * (i.e., the device's MSI-X capability structure "table size"), -EINVAL 69 + * if the device is not MSI-X capable, other errnos otherwise. 70 + */ 71 + int pci_msix_vec_count(struct pci_dev *dev) 72 + { 73 + u16 control; 74 + 75 + if (!dev->msix_cap) 76 + return -EINVAL; 77 + 78 + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); 79 + return msix_table_size(control); 80 + } 81 + EXPORT_SYMBOL(pci_msix_vec_count); 82 + 83 + /** 84 + * pci_enable_msix_range() - Enable MSI-X interrupt mode on device 85 + * @dev: the PCI device to operate on 86 + * @entries: input/output parameter, array of MSI-X configuration entries 87 + * @minvec: minimum required number of MSI-X vectors 88 + * @maxvec: maximum desired number of MSI-X vectors 89 + * 90 + * Legacy device driver API to enable MSI-X interrupt mode on device and 91 + * configure its MSI-X capability structure as appropriate. The passed 92 + * @entries array must have each of its members "entry" field set to a 93 + * desired (valid) MSI-X vector number, where the range of valid MSI-X 94 + * vector numbers can be queried through pci_msix_vec_count(). If 95 + * successful, the driver must invoke pci_disable_msix() on cleanup. 96 + * 97 + * NOTE: The newer pci_alloc_irq_vectors() / pci_free_irq_vectors() API 98 + * pair should, in general, be used instead. 99 + * 100 + * Return: number of MSI-X vectors allocated (which might be smaller 101 + * than @maxvecs), where Linux IRQ numbers for such allocated vectors 102 + * are saved back in the @entries array elements' "vector" field. Return 103 + * -ENOSPC if less than @minvecs interrupt vectors are available. 104 + * Return -EINVAL if one of the passed @entries members "entry" field 105 + * was invalid or a duplicate, or if plain MSI interrupts mode was 106 + * earlier enabled on device. Return other errnos otherwise. 107 + */ 108 + int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, 109 + int minvec, int maxvec) 110 + { 111 + return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL, 0); 112 + } 113 + EXPORT_SYMBOL(pci_enable_msix_range); 114 + 115 + /** 116 + * pci_msix_can_alloc_dyn - Query whether dynamic allocation after enabling 117 + * MSI-X is supported 118 + * 119 + * @dev: PCI device to operate on 120 + * 121 + * Return: True if supported, false otherwise 122 + */ 123 + bool pci_msix_can_alloc_dyn(struct pci_dev *dev) 124 + { 125 + if (!dev->msix_cap) 126 + return false; 127 + 128 + return pci_msi_domain_supports(dev, MSI_FLAG_PCI_MSIX_ALLOC_DYN, DENY_LEGACY); 129 + } 130 + EXPORT_SYMBOL_GPL(pci_msix_can_alloc_dyn); 131 + 132 + /** 133 + * pci_msix_alloc_irq_at - Allocate an MSI-X interrupt after enabling MSI-X 134 + * at a given MSI-X vector index or any free vector index 135 + * 136 + * @dev: PCI device to operate on 137 + * @index: Index to allocate. If @index == MSI_ANY_INDEX this allocates 138 + * the next free index in the MSI-X table 139 + * @affdesc: Optional pointer to an affinity descriptor structure. NULL otherwise 140 + * 141 + * Return: A struct msi_map 142 + * 143 + * On success msi_map::index contains the allocated index (>= 0) and 144 + * msi_map::virq contains the allocated Linux interrupt number (> 0). 145 + * 146 + * On fail msi_map::index contains the error code and msi_map::virq 147 + * is set to 0. 148 + */ 149 + struct msi_map pci_msix_alloc_irq_at(struct pci_dev *dev, unsigned int index, 150 + const struct irq_affinity_desc *affdesc) 151 + { 152 + struct msi_map map = { .index = -ENOTSUPP }; 153 + 154 + if (!dev->msix_enabled) 155 + return map; 156 + 157 + if (!pci_msix_can_alloc_dyn(dev)) 158 + return map; 159 + 160 + return msi_domain_alloc_irq_at(&dev->dev, MSI_DEFAULT_DOMAIN, index, affdesc, NULL); 161 + } 162 + EXPORT_SYMBOL_GPL(pci_msix_alloc_irq_at); 163 + 164 + /** 165 + * pci_msix_free_irq - Free an interrupt on a PCI/MSIX interrupt domain 166 + * which was allocated via pci_msix_alloc_irq_at() 167 + * 168 + * @dev: The PCI device to operate on 169 + * @map: A struct msi_map describing the interrupt to free 170 + * as returned from the allocation function. 171 + */ 172 + void pci_msix_free_irq(struct pci_dev *dev, struct msi_map map) 173 + { 174 + if (WARN_ON_ONCE(map.index < 0 || map.virq <= 0)) 175 + return; 176 + if (WARN_ON_ONCE(!pci_msix_can_alloc_dyn(dev))) 177 + return; 178 + msi_domain_free_irqs_range(&dev->dev, MSI_DEFAULT_DOMAIN, map.index, map.index); 179 + } 180 + EXPORT_SYMBOL_GPL(pci_msix_free_irq); 181 + 182 + /** 183 + * pci_disable_msix() - Disable MSI-X interrupt mode on device 184 + * @dev: the PCI device to operate on 185 + * 186 + * Legacy device driver API to disable MSI-X interrupt mode on device, 187 + * free earlier-allocated interrupt vectors, and restore INTx. 188 + * The PCI device Linux IRQ (@dev->irq) is restored to its default pin 189 + * assertion IRQ. This is the cleanup pair of pci_enable_msix_range(). 190 + * 191 + * NOTE: The newer pci_alloc_irq_vectors() / pci_free_irq_vectors() API 192 + * pair should, in general, be used instead. 193 + */ 194 + void pci_disable_msix(struct pci_dev *dev) 195 + { 196 + if (!pci_msi_enabled() || !dev || !dev->msix_enabled) 197 + return; 198 + 199 + msi_lock_descs(&dev->dev); 200 + pci_msix_shutdown(dev); 201 + pci_free_msi_irqs(dev); 202 + msi_unlock_descs(&dev->dev); 203 + } 204 + EXPORT_SYMBOL(pci_disable_msix); 205 + 206 + /** 207 + * pci_alloc_irq_vectors() - Allocate multiple device interrupt vectors 208 + * @dev: the PCI device to operate on 209 + * @min_vecs: minimum required number of vectors (must be >= 1) 210 + * @max_vecs: maximum desired number of vectors 211 + * @flags: One or more of: 212 + * 213 + * * %PCI_IRQ_MSIX Allow trying MSI-X vector allocations 214 + * * %PCI_IRQ_MSI Allow trying MSI vector allocations 215 + * 216 + * * %PCI_IRQ_LEGACY Allow trying legacy INTx interrupts, if 217 + * and only if @min_vecs == 1 218 + * 219 + * * %PCI_IRQ_AFFINITY Auto-manage IRQs affinity by spreading 220 + * the vectors around available CPUs 221 + * 222 + * Allocate up to @max_vecs interrupt vectors on device. MSI-X irq 223 + * vector allocation has a higher precedence over plain MSI, which has a 224 + * higher precedence over legacy INTx emulation. 225 + * 226 + * Upon a successful allocation, the caller should use pci_irq_vector() 227 + * to get the Linux IRQ number to be passed to request_threaded_irq(). 228 + * The driver must call pci_free_irq_vectors() on cleanup. 229 + * 230 + * Return: number of allocated vectors (which might be smaller than 231 + * @max_vecs), -ENOSPC if less than @min_vecs interrupt vectors are 232 + * available, other errnos otherwise. 233 + */ 234 + int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 235 + unsigned int max_vecs, unsigned int flags) 236 + { 237 + return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, 238 + flags, NULL); 239 + } 240 + EXPORT_SYMBOL(pci_alloc_irq_vectors); 241 + 242 + /** 243 + * pci_alloc_irq_vectors_affinity() - Allocate multiple device interrupt 244 + * vectors with affinity requirements 245 + * @dev: the PCI device to operate on 246 + * @min_vecs: minimum required number of vectors (must be >= 1) 247 + * @max_vecs: maximum desired number of vectors 248 + * @flags: allocation flags, as in pci_alloc_irq_vectors() 249 + * @affd: affinity requirements (can be %NULL). 250 + * 251 + * Same as pci_alloc_irq_vectors(), but with the extra @affd parameter. 252 + * Check that function docs, and &struct irq_affinity, for more details. 253 + */ 254 + int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, 255 + unsigned int max_vecs, unsigned int flags, 256 + struct irq_affinity *affd) 257 + { 258 + struct irq_affinity msi_default_affd = {0}; 259 + int nvecs = -ENOSPC; 260 + 261 + if (flags & PCI_IRQ_AFFINITY) { 262 + if (!affd) 263 + affd = &msi_default_affd; 264 + } else { 265 + if (WARN_ON(affd)) 266 + affd = NULL; 267 + } 268 + 269 + if (flags & PCI_IRQ_MSIX) { 270 + nvecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, 271 + affd, flags); 272 + if (nvecs > 0) 273 + return nvecs; 274 + } 275 + 276 + if (flags & PCI_IRQ_MSI) { 277 + nvecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd); 278 + if (nvecs > 0) 279 + return nvecs; 280 + } 281 + 282 + /* use legacy IRQ if allowed */ 283 + if (flags & PCI_IRQ_LEGACY) { 284 + if (min_vecs == 1 && dev->irq) { 285 + /* 286 + * Invoke the affinity spreading logic to ensure that 287 + * the device driver can adjust queue configuration 288 + * for the single interrupt case. 289 + */ 290 + if (affd) 291 + irq_create_affinity_masks(1, affd); 292 + pci_intx(dev, 1); 293 + return 1; 294 + } 295 + } 296 + 297 + return nvecs; 298 + } 299 + EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity); 300 + 301 + /** 302 + * pci_irq_vector() - Get Linux IRQ number of a device interrupt vector 303 + * @dev: the PCI device to operate on 304 + * @nr: device-relative interrupt vector index (0-based); has different 305 + * meanings, depending on interrupt mode: 306 + * 307 + * * MSI-X the index in the MSI-X vector table 308 + * * MSI the index of the enabled MSI vectors 309 + * * INTx must be 0 310 + * 311 + * Return: the Linux IRQ number, or -EINVAL if @nr is out of range 312 + */ 313 + int pci_irq_vector(struct pci_dev *dev, unsigned int nr) 314 + { 315 + unsigned int irq; 316 + 317 + if (!dev->msi_enabled && !dev->msix_enabled) 318 + return !nr ? dev->irq : -EINVAL; 319 + 320 + irq = msi_get_virq(&dev->dev, nr); 321 + return irq ? irq : -EINVAL; 322 + } 323 + EXPORT_SYMBOL(pci_irq_vector); 324 + 325 + /** 326 + * pci_irq_get_affinity() - Get a device interrupt vector affinity 327 + * @dev: the PCI device to operate on 328 + * @nr: device-relative interrupt vector index (0-based); has different 329 + * meanings, depending on interrupt mode: 330 + * 331 + * * MSI-X the index in the MSI-X vector table 332 + * * MSI the index of the enabled MSI vectors 333 + * * INTx must be 0 334 + * 335 + * Return: MSI/MSI-X vector affinity, NULL if @nr is out of range or if 336 + * the MSI(-X) vector was allocated without explicit affinity 337 + * requirements (e.g., by pci_enable_msi(), pci_enable_msix_range(), or 338 + * pci_alloc_irq_vectors() without the %PCI_IRQ_AFFINITY flag). Return a 339 + * generic set of CPU IDs representing all possible CPUs available 340 + * during system boot if the device is in legacy INTx mode. 341 + */ 342 + const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) 343 + { 344 + int idx, irq = pci_irq_vector(dev, nr); 345 + struct msi_desc *desc; 346 + 347 + if (WARN_ON_ONCE(irq <= 0)) 348 + return NULL; 349 + 350 + desc = irq_get_msi_desc(irq); 351 + /* Non-MSI does not have the information handy */ 352 + if (!desc) 353 + return cpu_possible_mask; 354 + 355 + /* MSI[X] interrupts can be allocated without affinity descriptor */ 356 + if (!desc->affinity) 357 + return NULL; 358 + 359 + /* 360 + * MSI has a mask array in the descriptor. 361 + * MSI-X has a single mask. 362 + */ 363 + idx = dev->msi_enabled ? nr : 0; 364 + return &desc->affinity[idx].mask; 365 + } 366 + EXPORT_SYMBOL(pci_irq_get_affinity); 367 + 368 + /** 369 + * pci_ims_alloc_irq - Allocate an interrupt on a PCI/IMS interrupt domain 370 + * @dev: The PCI device to operate on 371 + * @icookie: Pointer to an IMS implementation specific cookie for this 372 + * IMS instance (PASID, queue ID, pointer...). 373 + * The cookie content is copied into the MSI descriptor for the 374 + * interrupt chip callbacks or domain specific setup functions. 375 + * @affdesc: Optional pointer to an interrupt affinity descriptor 376 + * 377 + * There is no index for IMS allocations as IMS is an implementation 378 + * specific storage and does not have any direct associations between 379 + * index, which might be a pure software construct, and device 380 + * functionality. This association is established by the driver either via 381 + * the index - if there is a hardware table - or in case of purely software 382 + * managed IMS implementation the association happens via the 383 + * irq_write_msi_msg() callback of the implementation specific interrupt 384 + * chip, which utilizes the provided @icookie to store the MSI message in 385 + * the appropriate place. 386 + * 387 + * Return: A struct msi_map 388 + * 389 + * On success msi_map::index contains the allocated index (>= 0) and 390 + * msi_map::virq the allocated Linux interrupt number (> 0). 391 + * 392 + * On fail msi_map::index contains the error code and msi_map::virq 393 + * is set to 0. 394 + */ 395 + struct msi_map pci_ims_alloc_irq(struct pci_dev *dev, union msi_instance_cookie *icookie, 396 + const struct irq_affinity_desc *affdesc) 397 + { 398 + return msi_domain_alloc_irq_at(&dev->dev, MSI_SECONDARY_DOMAIN, MSI_ANY_INDEX, 399 + affdesc, icookie); 400 + } 401 + EXPORT_SYMBOL_GPL(pci_ims_alloc_irq); 402 + 403 + /** 404 + * pci_ims_free_irq - Allocate an interrupt on a PCI/IMS interrupt domain 405 + * which was allocated via pci_ims_alloc_irq() 406 + * @dev: The PCI device to operate on 407 + * @map: A struct msi_map describing the interrupt to free as 408 + * returned from pci_ims_alloc_irq() 409 + */ 410 + void pci_ims_free_irq(struct pci_dev *dev, struct msi_map map) 411 + { 412 + if (WARN_ON_ONCE(map.index < 0 || map.virq <= 0)) 413 + return; 414 + msi_domain_free_irqs_range(&dev->dev, MSI_SECONDARY_DOMAIN, map.index, map.index); 415 + } 416 + EXPORT_SYMBOL_GPL(pci_ims_free_irq); 417 + 418 + /** 419 + * pci_free_irq_vectors() - Free previously allocated IRQs for a device 420 + * @dev: the PCI device to operate on 421 + * 422 + * Undo the interrupt vector allocations and possible device MSI/MSI-X 423 + * enablement earlier done through pci_alloc_irq_vectors_affinity() or 424 + * pci_alloc_irq_vectors(). 425 + */ 426 + void pci_free_irq_vectors(struct pci_dev *dev) 427 + { 428 + pci_disable_msix(dev); 429 + pci_disable_msi(dev); 430 + } 431 + EXPORT_SYMBOL(pci_free_irq_vectors); 432 + 433 + /** 434 + * pci_restore_msi_state() - Restore cached MSI(-X) state on device 435 + * @dev: the PCI device to operate on 436 + * 437 + * Write the Linux-cached MSI(-X) state back on device. This is 438 + * typically useful upon system resume, or after an error-recovery PCI 439 + * adapter reset. 440 + */ 441 + void pci_restore_msi_state(struct pci_dev *dev) 442 + { 443 + __pci_restore_msi_state(dev); 444 + __pci_restore_msix_state(dev); 445 + } 446 + EXPORT_SYMBOL_GPL(pci_restore_msi_state); 447 + 448 + /** 449 + * pci_msi_enabled() - Are MSI(-X) interrupts enabled system-wide? 450 + * 451 + * Return: true if MSI has not been globally disabled through ACPI FADT, 452 + * PCI bridge quirks, or the "pci=nomsi" kernel command-line option. 453 + */ 454 + int pci_msi_enabled(void) 455 + { 456 + return pci_msi_enable; 457 + } 458 + EXPORT_SYMBOL(pci_msi_enabled);
+287 -82
drivers/pci/msi/irqdomain.c
··· 14 14 15 15 domain = dev_get_msi_domain(&dev->dev); 16 16 if (domain && irq_domain_is_hierarchy(domain)) 17 - return msi_domain_alloc_irqs_descs_locked(domain, &dev->dev, nvec); 17 + return msi_domain_alloc_irqs_all_locked(&dev->dev, MSI_DEFAULT_DOMAIN, nvec); 18 18 19 19 return pci_msi_legacy_setup_msi_irqs(dev, nvec, type); 20 20 } ··· 24 24 struct irq_domain *domain; 25 25 26 26 domain = dev_get_msi_domain(&dev->dev); 27 - if (domain && irq_domain_is_hierarchy(domain)) 28 - msi_domain_free_irqs_descs_locked(domain, &dev->dev); 29 - else 27 + if (domain && irq_domain_is_hierarchy(domain)) { 28 + msi_domain_free_irqs_all_locked(&dev->dev, MSI_DEFAULT_DOMAIN); 29 + } else { 30 30 pci_msi_legacy_teardown_msi_irqs(dev); 31 - msi_free_msi_descs(&dev->dev); 31 + msi_free_msi_descs(&dev->dev); 32 + } 32 33 } 33 34 34 35 /** ··· 64 63 (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27; 65 64 } 66 65 67 - static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc) 68 - { 69 - return !desc->pci.msi_attrib.is_msix && desc->nvec_used > 1; 70 - } 71 - 72 - /** 73 - * pci_msi_domain_check_cap - Verify that @domain supports the capabilities 74 - * for @dev 75 - * @domain: The interrupt domain to check 76 - * @info: The domain info for verification 77 - * @dev: The device to check 78 - * 79 - * Returns: 80 - * 0 if the functionality is supported 81 - * 1 if Multi MSI is requested, but the domain does not support it 82 - * -ENOTSUPP otherwise 83 - */ 84 - static int pci_msi_domain_check_cap(struct irq_domain *domain, 85 - struct msi_domain_info *info, 86 - struct device *dev) 87 - { 88 - struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL); 89 - 90 - /* Special handling to support __pci_enable_msi_range() */ 91 - if (pci_msi_desc_is_multi_msi(desc) && 92 - !(info->flags & MSI_FLAG_MULTI_PCI_MSI)) 93 - return 1; 94 - 95 - if (desc->pci.msi_attrib.is_msix) { 96 - if (!(info->flags & MSI_FLAG_PCI_MSIX)) 97 - return -ENOTSUPP; 98 - 99 - if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) { 100 - unsigned int idx = 0; 101 - 102 - /* Check for gaps in the entry indices */ 103 - msi_for_each_desc(desc, dev, MSI_DESC_ALL) { 104 - if (desc->msi_index != idx++) 105 - return -ENOTSUPP; 106 - } 107 - } 108 - } 109 - return 0; 110 - } 111 - 112 66 static void pci_msi_domain_set_desc(msi_alloc_info_t *arg, 113 67 struct msi_desc *desc) 114 68 { ··· 73 117 74 118 static struct msi_domain_ops pci_msi_domain_ops_default = { 75 119 .set_desc = pci_msi_domain_set_desc, 76 - .msi_check = pci_msi_domain_check_cap, 77 120 }; 78 121 79 122 static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info) ··· 84 129 } else { 85 130 if (ops->set_desc == NULL) 86 131 ops->set_desc = pci_msi_domain_set_desc; 87 - if (ops->msi_check == NULL) 88 - ops->msi_check = pci_msi_domain_check_cap; 89 132 } 90 133 } 91 134 ··· 115 162 struct msi_domain_info *info, 116 163 struct irq_domain *parent) 117 164 { 118 - struct irq_domain *domain; 119 - 120 165 if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) 121 166 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; 122 167 ··· 123 172 if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) 124 173 pci_msi_domain_update_chip_ops(info); 125 174 175 + /* Let the core code free MSI descriptors when freeing interrupts */ 176 + info->flags |= MSI_FLAG_FREE_MSI_DESCS; 177 + 126 178 info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS; 127 179 if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE)) 128 180 info->flags |= MSI_FLAG_MUST_REACTIVATE; 129 181 130 182 /* PCI-MSI is oneshot-safe */ 131 183 info->chip->flags |= IRQCHIP_ONESHOT_SAFE; 184 + /* Let the core update the bus token */ 185 + info->bus_token = DOMAIN_BUS_PCI_MSI; 132 186 133 - domain = msi_create_irq_domain(fwnode, info, parent); 134 - if (!domain) 135 - return NULL; 136 - 137 - irq_domain_update_bus_token(domain, DOMAIN_BUS_PCI_MSI); 138 - return domain; 187 + return msi_create_irq_domain(fwnode, info, parent); 139 188 } 140 189 EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain); 190 + 191 + /* 192 + * Per device MSI[-X] domain functionality 193 + */ 194 + static void pci_device_domain_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) 195 + { 196 + arg->desc = desc; 197 + arg->hwirq = desc->msi_index; 198 + } 199 + 200 + static void pci_irq_mask_msi(struct irq_data *data) 201 + { 202 + struct msi_desc *desc = irq_data_get_msi_desc(data); 203 + 204 + pci_msi_mask(desc, BIT(data->irq - desc->irq)); 205 + } 206 + 207 + static void pci_irq_unmask_msi(struct irq_data *data) 208 + { 209 + struct msi_desc *desc = irq_data_get_msi_desc(data); 210 + 211 + pci_msi_unmask(desc, BIT(data->irq - desc->irq)); 212 + } 213 + 214 + #ifdef CONFIG_GENERIC_IRQ_RESERVATION_MODE 215 + # define MSI_REACTIVATE MSI_FLAG_MUST_REACTIVATE 216 + #else 217 + # define MSI_REACTIVATE 0 218 + #endif 219 + 220 + #define MSI_COMMON_FLAGS (MSI_FLAG_FREE_MSI_DESCS | \ 221 + MSI_FLAG_ACTIVATE_EARLY | \ 222 + MSI_FLAG_DEV_SYSFS | \ 223 + MSI_REACTIVATE) 224 + 225 + static const struct msi_domain_template pci_msi_template = { 226 + .chip = { 227 + .name = "PCI-MSI", 228 + .irq_mask = pci_irq_mask_msi, 229 + .irq_unmask = pci_irq_unmask_msi, 230 + .irq_write_msi_msg = pci_msi_domain_write_msg, 231 + .flags = IRQCHIP_ONESHOT_SAFE, 232 + }, 233 + 234 + .ops = { 235 + .set_desc = pci_device_domain_set_desc, 236 + }, 237 + 238 + .info = { 239 + .flags = MSI_COMMON_FLAGS | MSI_FLAG_MULTI_PCI_MSI, 240 + .bus_token = DOMAIN_BUS_PCI_DEVICE_MSI, 241 + }, 242 + }; 243 + 244 + static void pci_irq_mask_msix(struct irq_data *data) 245 + { 246 + pci_msix_mask(irq_data_get_msi_desc(data)); 247 + } 248 + 249 + static void pci_irq_unmask_msix(struct irq_data *data) 250 + { 251 + pci_msix_unmask(irq_data_get_msi_desc(data)); 252 + } 253 + 254 + static void pci_msix_prepare_desc(struct irq_domain *domain, msi_alloc_info_t *arg, 255 + struct msi_desc *desc) 256 + { 257 + /* Don't fiddle with preallocated MSI descriptors */ 258 + if (!desc->pci.mask_base) 259 + msix_prepare_msi_desc(to_pci_dev(desc->dev), desc); 260 + } 261 + 262 + static const struct msi_domain_template pci_msix_template = { 263 + .chip = { 264 + .name = "PCI-MSIX", 265 + .irq_mask = pci_irq_mask_msix, 266 + .irq_unmask = pci_irq_unmask_msix, 267 + .irq_write_msi_msg = pci_msi_domain_write_msg, 268 + .flags = IRQCHIP_ONESHOT_SAFE, 269 + }, 270 + 271 + .ops = { 272 + .prepare_desc = pci_msix_prepare_desc, 273 + .set_desc = pci_device_domain_set_desc, 274 + }, 275 + 276 + .info = { 277 + .flags = MSI_COMMON_FLAGS | MSI_FLAG_PCI_MSIX | 278 + MSI_FLAG_PCI_MSIX_ALLOC_DYN, 279 + .bus_token = DOMAIN_BUS_PCI_DEVICE_MSIX, 280 + }, 281 + }; 282 + 283 + static bool pci_match_device_domain(struct pci_dev *pdev, enum irq_domain_bus_token bus_token) 284 + { 285 + return msi_match_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN, bus_token); 286 + } 287 + 288 + static bool pci_create_device_domain(struct pci_dev *pdev, const struct msi_domain_template *tmpl, 289 + unsigned int hwsize) 290 + { 291 + struct irq_domain *domain = dev_get_msi_domain(&pdev->dev); 292 + 293 + if (!domain || !irq_domain_is_msi_parent(domain)) 294 + return true; 295 + 296 + return msi_create_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN, tmpl, 297 + hwsize, NULL, NULL); 298 + } 299 + 300 + /** 301 + * pci_setup_msi_device_domain - Setup a device MSI interrupt domain 302 + * @pdev: The PCI device to create the domain on 303 + * 304 + * Return: 305 + * True when: 306 + * - The device does not have a MSI parent irq domain associated, 307 + * which keeps the legacy architecture specific and the global 308 + * PCI/MSI domain models working 309 + * - The MSI domain exists already 310 + * - The MSI domain was successfully allocated 311 + * False when: 312 + * - MSI-X is enabled 313 + * - The domain creation fails. 314 + * 315 + * The created MSI domain is preserved until: 316 + * - The device is removed 317 + * - MSI is disabled and a MSI-X domain is created 318 + */ 319 + bool pci_setup_msi_device_domain(struct pci_dev *pdev) 320 + { 321 + if (WARN_ON_ONCE(pdev->msix_enabled)) 322 + return false; 323 + 324 + if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSI)) 325 + return true; 326 + if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSIX)) 327 + msi_remove_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN); 328 + 329 + return pci_create_device_domain(pdev, &pci_msi_template, 1); 330 + } 331 + 332 + /** 333 + * pci_setup_msix_device_domain - Setup a device MSI-X interrupt domain 334 + * @pdev: The PCI device to create the domain on 335 + * @hwsize: The size of the MSI-X vector table 336 + * 337 + * Return: 338 + * True when: 339 + * - The device does not have a MSI parent irq domain associated, 340 + * which keeps the legacy architecture specific and the global 341 + * PCI/MSI domain models working 342 + * - The MSI-X domain exists already 343 + * - The MSI-X domain was successfully allocated 344 + * False when: 345 + * - MSI is enabled 346 + * - The domain creation fails. 347 + * 348 + * The created MSI-X domain is preserved until: 349 + * - The device is removed 350 + * - MSI-X is disabled and a MSI domain is created 351 + */ 352 + bool pci_setup_msix_device_domain(struct pci_dev *pdev, unsigned int hwsize) 353 + { 354 + if (WARN_ON_ONCE(pdev->msi_enabled)) 355 + return false; 356 + 357 + if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSIX)) 358 + return true; 359 + if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSI)) 360 + msi_remove_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN); 361 + 362 + return pci_create_device_domain(pdev, &pci_msix_template, hwsize); 363 + } 364 + 365 + /** 366 + * pci_msi_domain_supports - Check for support of a particular feature flag 367 + * @pdev: The PCI device to operate on 368 + * @feature_mask: The feature mask to check for (full match) 369 + * @mode: If ALLOW_LEGACY this grants the feature when there is no irq domain 370 + * associated to the device. If DENY_LEGACY the lack of an irq domain 371 + * makes the feature unsupported 372 + */ 373 + bool pci_msi_domain_supports(struct pci_dev *pdev, unsigned int feature_mask, 374 + enum support_mode mode) 375 + { 376 + struct msi_domain_info *info; 377 + struct irq_domain *domain; 378 + unsigned int supported; 379 + 380 + domain = dev_get_msi_domain(&pdev->dev); 381 + 382 + if (!domain || !irq_domain_is_hierarchy(domain)) 383 + return mode == ALLOW_LEGACY; 384 + 385 + if (!irq_domain_is_msi_parent(domain)) { 386 + /* 387 + * For "global" PCI/MSI interrupt domains the associated 388 + * msi_domain_info::flags is the authoritive source of 389 + * information. 390 + */ 391 + info = domain->host_data; 392 + supported = info->flags; 393 + } else { 394 + /* 395 + * For MSI parent domains the supported feature set 396 + * is avaliable in the parent ops. This makes checks 397 + * possible before actually instantiating the 398 + * per device domain because the parent is never 399 + * expanding the PCI/MSI functionality. 400 + */ 401 + supported = domain->msi_parent_ops->supported_flags; 402 + } 403 + 404 + return (supported & feature_mask) == feature_mask; 405 + } 406 + 407 + /** 408 + * pci_create_ims_domain - Create a secondary IMS domain for a PCI device 409 + * @pdev: The PCI device to operate on 410 + * @template: The MSI info template which describes the domain 411 + * @hwsize: The size of the hardware entry table or 0 if the domain 412 + * is purely software managed 413 + * @data: Optional pointer to domain specific data to be stored 414 + * in msi_domain_info::data 415 + * 416 + * Return: True on success, false otherwise 417 + * 418 + * An IMS domain is expected to have the following constraints: 419 + * - The index space is managed by the core code 420 + * 421 + * - There is no requirement for consecutive index ranges 422 + * 423 + * - The interrupt chip must provide the following callbacks: 424 + * - irq_mask() 425 + * - irq_unmask() 426 + * - irq_write_msi_msg() 427 + * 428 + * - The interrupt chip must provide the following optional callbacks 429 + * when the irq_mask(), irq_unmask() and irq_write_msi_msg() callbacks 430 + * cannot operate directly on hardware, e.g. in the case that the 431 + * interrupt message store is in queue memory: 432 + * - irq_bus_lock() 433 + * - irq_bus_unlock() 434 + * 435 + * These callbacks are invoked from preemptible task context and are 436 + * allowed to sleep. In this case the mandatory callbacks above just 437 + * store the information. The irq_bus_unlock() callback is supposed 438 + * to make the change effective before returning. 439 + * 440 + * - Interrupt affinity setting is handled by the underlying parent 441 + * interrupt domain and communicated to the IMS domain via 442 + * irq_write_msi_msg(). 443 + * 444 + * The domain is automatically destroyed when the PCI device is removed. 445 + */ 446 + bool pci_create_ims_domain(struct pci_dev *pdev, const struct msi_domain_template *template, 447 + unsigned int hwsize, void *data) 448 + { 449 + struct irq_domain *domain = dev_get_msi_domain(&pdev->dev); 450 + 451 + if (!domain || !irq_domain_is_msi_parent(domain)) 452 + return false; 453 + 454 + if (template->info.bus_token != DOMAIN_BUS_PCI_DEVICE_IMS || 455 + !(template->info.flags & MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS) || 456 + !(template->info.flags & MSI_FLAG_FREE_MSI_DESCS) || 457 + !template->chip.irq_mask || !template->chip.irq_unmask || 458 + !template->chip.irq_write_msi_msg || template->chip.irq_set_affinity) 459 + return false; 460 + 461 + return msi_create_device_irq_domain(&pdev->dev, MSI_SECONDARY_DOMAIN, template, 462 + hwsize, data, NULL); 463 + } 464 + EXPORT_SYMBOL_GPL(pci_create_ims_domain); 141 465 142 466 /* 143 467 * Users of the generic MSI infrastructure expect a device to have a single ID, ··· 482 256 dom = iort_get_device_domain(&pdev->dev, rid, 483 257 DOMAIN_BUS_PCI_MSI); 484 258 return dom; 485 - } 486 - 487 - /** 488 - * pci_dev_has_special_msi_domain - Check whether the device is handled by 489 - * a non-standard PCI-MSI domain 490 - * @pdev: The PCI device to check. 491 - * 492 - * Returns: True if the device irqdomain or the bus irqdomain is 493 - * non-standard PCI/MSI. 494 - */ 495 - bool pci_dev_has_special_msi_domain(struct pci_dev *pdev) 496 - { 497 - struct irq_domain *dom = dev_get_msi_domain(&pdev->dev); 498 - 499 - if (!dom) 500 - dom = dev_get_msi_domain(&pdev->bus->dev); 501 - 502 - if (!dom) 503 - return true; 504 - 505 - return dom->bus_token != DOMAIN_BUS_PCI_MSI; 506 259 }
+560 -788
drivers/pci/msi/msi.c
··· 13 13 #include "../pci.h" 14 14 #include "msi.h" 15 15 16 - static int pci_msi_enable = 1; 16 + int pci_msi_enable = 1; 17 17 int pci_msi_ignore_mask; 18 18 19 - static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 set) 19 + /** 20 + * pci_msi_supported - check whether MSI may be enabled on a device 21 + * @dev: pointer to the pci_dev data structure of MSI device function 22 + * @nvec: how many MSIs have been requested? 23 + * 24 + * Look at global flags, the device itself, and its parent buses 25 + * to determine if MSI/-X are supported for the device. If MSI/-X is 26 + * supported return 1, else return 0. 27 + **/ 28 + static int pci_msi_supported(struct pci_dev *dev, int nvec) 29 + { 30 + struct pci_bus *bus; 31 + 32 + /* MSI must be globally enabled and supported by the device */ 33 + if (!pci_msi_enable) 34 + return 0; 35 + 36 + if (!dev || dev->no_msi) 37 + return 0; 38 + 39 + /* 40 + * You can't ask to have 0 or less MSIs configured. 41 + * a) it's stupid .. 42 + * b) the list manipulation code assumes nvec >= 1. 43 + */ 44 + if (nvec < 1) 45 + return 0; 46 + 47 + /* 48 + * Any bridge which does NOT route MSI transactions from its 49 + * secondary bus to its primary bus must set NO_MSI flag on 50 + * the secondary pci_bus. 51 + * 52 + * The NO_MSI flag can either be set directly by: 53 + * - arch-specific PCI host bus controller drivers (deprecated) 54 + * - quirks for specific PCI bridges 55 + * 56 + * or indirectly by platform-specific PCI host bridge drivers by 57 + * advertising the 'msi_domain' property, which results in 58 + * the NO_MSI flag when no MSI domain is found for this bridge 59 + * at probe time. 60 + */ 61 + for (bus = dev->bus; bus; bus = bus->parent) 62 + if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 63 + return 0; 64 + 65 + return 1; 66 + } 67 + 68 + static void pcim_msi_release(void *pcidev) 69 + { 70 + struct pci_dev *dev = pcidev; 71 + 72 + dev->is_msi_managed = false; 73 + pci_free_irq_vectors(dev); 74 + } 75 + 76 + /* 77 + * Needs to be separate from pcim_release to prevent an ordering problem 78 + * vs. msi_device_data_release() in the MSI core code. 79 + */ 80 + static int pcim_setup_msi_release(struct pci_dev *dev) 81 + { 82 + int ret; 83 + 84 + if (!pci_is_managed(dev) || dev->is_msi_managed) 85 + return 0; 86 + 87 + ret = devm_add_action(&dev->dev, pcim_msi_release, dev); 88 + if (!ret) 89 + dev->is_msi_managed = true; 90 + return ret; 91 + } 92 + 93 + /* 94 + * Ordering vs. devres: msi device data has to be installed first so that 95 + * pcim_msi_release() is invoked before it on device release. 96 + */ 97 + static int pci_setup_msi_context(struct pci_dev *dev) 98 + { 99 + int ret = msi_setup_device_data(&dev->dev); 100 + 101 + if (!ret) 102 + ret = pcim_setup_msi_release(dev); 103 + return ret; 104 + } 105 + 106 + /* 107 + * Helper functions for mask/unmask and MSI message handling 108 + */ 109 + 110 + void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 set) 20 111 { 21 112 raw_spinlock_t *lock = &to_pci_dev(desc->dev)->msi_lock; 22 113 unsigned long flags; ··· 121 30 pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->pci.mask_pos, 122 31 desc->pci.msi_mask); 123 32 raw_spin_unlock_irqrestore(lock, flags); 124 - } 125 - 126 - static inline void pci_msi_mask(struct msi_desc *desc, u32 mask) 127 - { 128 - pci_msi_update_mask(desc, 0, mask); 129 - } 130 - 131 - static inline void pci_msi_unmask(struct msi_desc *desc, u32 mask) 132 - { 133 - pci_msi_update_mask(desc, mask, 0); 134 - } 135 - 136 - static inline void __iomem *pci_msix_desc_addr(struct msi_desc *desc) 137 - { 138 - return desc->pci.mask_base + desc->msi_index * PCI_MSIX_ENTRY_SIZE; 139 - } 140 - 141 - /* 142 - * This internal function does not flush PCI writes to the device. All 143 - * users must ensure that they read from the device before either assuming 144 - * that the device state is up to date, or returning out of this file. 145 - * It does not affect the msi_desc::msix_ctrl cache either. Use with care! 146 - */ 147 - static void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl) 148 - { 149 - void __iomem *desc_addr = pci_msix_desc_addr(desc); 150 - 151 - if (desc->pci.msi_attrib.can_mask) 152 - writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); 153 - } 154 - 155 - static inline void pci_msix_mask(struct msi_desc *desc) 156 - { 157 - desc->pci.msix_ctrl |= PCI_MSIX_ENTRY_CTRL_MASKBIT; 158 - pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 159 - /* Flush write to device */ 160 - readl(desc->pci.mask_base); 161 - } 162 - 163 - static inline void pci_msix_unmask(struct msi_desc *desc) 164 - { 165 - desc->pci.msix_ctrl &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; 166 - pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 167 - } 168 - 169 - static void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask) 170 - { 171 - if (desc->pci.msi_attrib.is_msix) 172 - pci_msix_mask(desc); 173 - else 174 - pci_msi_mask(desc, mask); 175 - } 176 - 177 - static void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask) 178 - { 179 - if (desc->pci.msi_attrib.is_msix) 180 - pci_msix_unmask(desc); 181 - else 182 - pci_msi_unmask(desc, mask); 183 33 } 184 34 185 35 /** ··· 180 148 } 181 149 } 182 150 151 + static inline void pci_write_msg_msi(struct pci_dev *dev, struct msi_desc *desc, 152 + struct msi_msg *msg) 153 + { 154 + int pos = dev->msi_cap; 155 + u16 msgctl; 156 + 157 + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); 158 + msgctl &= ~PCI_MSI_FLAGS_QSIZE; 159 + msgctl |= desc->pci.msi_attrib.multiple << 4; 160 + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); 161 + 162 + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, msg->address_lo); 163 + if (desc->pci.msi_attrib.is_64) { 164 + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, msg->address_hi); 165 + pci_write_config_word(dev, pos + PCI_MSI_DATA_64, msg->data); 166 + } else { 167 + pci_write_config_word(dev, pos + PCI_MSI_DATA_32, msg->data); 168 + } 169 + /* Ensure that the writes are visible in the device */ 170 + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); 171 + } 172 + 173 + static inline void pci_write_msg_msix(struct msi_desc *desc, struct msi_msg *msg) 174 + { 175 + void __iomem *base = pci_msix_desc_addr(desc); 176 + u32 ctrl = desc->pci.msix_ctrl; 177 + bool unmasked = !(ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT); 178 + 179 + if (desc->pci.msi_attrib.is_virtual) 180 + return; 181 + /* 182 + * The specification mandates that the entry is masked 183 + * when the message is modified: 184 + * 185 + * "If software changes the Address or Data value of an 186 + * entry while the entry is unmasked, the result is 187 + * undefined." 188 + */ 189 + if (unmasked) 190 + pci_msix_write_vector_ctrl(desc, ctrl | PCI_MSIX_ENTRY_CTRL_MASKBIT); 191 + 192 + writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); 193 + writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); 194 + writel(msg->data, base + PCI_MSIX_ENTRY_DATA); 195 + 196 + if (unmasked) 197 + pci_msix_write_vector_ctrl(desc, ctrl); 198 + 199 + /* Ensure that the writes are visible in the device */ 200 + readl(base + PCI_MSIX_ENTRY_DATA); 201 + } 202 + 183 203 void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) 184 204 { 185 205 struct pci_dev *dev = msi_desc_to_pci_dev(entry); ··· 239 155 if (dev->current_state != PCI_D0 || pci_dev_is_disconnected(dev)) { 240 156 /* Don't touch the hardware now */ 241 157 } else if (entry->pci.msi_attrib.is_msix) { 242 - void __iomem *base = pci_msix_desc_addr(entry); 243 - u32 ctrl = entry->pci.msix_ctrl; 244 - bool unmasked = !(ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT); 245 - 246 - if (entry->pci.msi_attrib.is_virtual) 247 - goto skip; 248 - 249 - /* 250 - * The specification mandates that the entry is masked 251 - * when the message is modified: 252 - * 253 - * "If software changes the Address or Data value of an 254 - * entry while the entry is unmasked, the result is 255 - * undefined." 256 - */ 257 - if (unmasked) 258 - pci_msix_write_vector_ctrl(entry, ctrl | PCI_MSIX_ENTRY_CTRL_MASKBIT); 259 - 260 - writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); 261 - writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); 262 - writel(msg->data, base + PCI_MSIX_ENTRY_DATA); 263 - 264 - if (unmasked) 265 - pci_msix_write_vector_ctrl(entry, ctrl); 266 - 267 - /* Ensure that the writes are visible in the device */ 268 - readl(base + PCI_MSIX_ENTRY_DATA); 158 + pci_write_msg_msix(entry, msg); 269 159 } else { 270 - int pos = dev->msi_cap; 271 - u16 msgctl; 272 - 273 - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); 274 - msgctl &= ~PCI_MSI_FLAGS_QSIZE; 275 - msgctl |= entry->pci.msi_attrib.multiple << 4; 276 - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); 277 - 278 - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, 279 - msg->address_lo); 280 - if (entry->pci.msi_attrib.is_64) { 281 - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, 282 - msg->address_hi); 283 - pci_write_config_word(dev, pos + PCI_MSI_DATA_64, 284 - msg->data); 285 - } else { 286 - pci_write_config_word(dev, pos + PCI_MSI_DATA_32, 287 - msg->data); 288 - } 289 - /* Ensure that the writes are visible in the device */ 290 - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); 160 + pci_write_msg_msi(dev, entry, msg); 291 161 } 292 162 293 - skip: 294 163 entry->msg = *msg; 295 164 296 165 if (entry->write_msi_msg) 297 166 entry->write_msi_msg(entry, entry->write_msi_msg_data); 298 - 299 167 } 300 168 301 169 void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) ··· 258 222 } 259 223 EXPORT_SYMBOL_GPL(pci_write_msi_msg); 260 224 261 - static void free_msi_irqs(struct pci_dev *dev) 262 - { 263 - pci_msi_teardown_msi_irqs(dev); 264 225 265 - if (dev->msix_base) { 266 - iounmap(dev->msix_base); 267 - dev->msix_base = NULL; 268 - } 269 - } 226 + /* PCI/MSI specific functionality */ 270 227 271 228 static void pci_intx_for_msi(struct pci_dev *dev, int enable) 272 229 { ··· 276 247 if (enable) 277 248 control |= PCI_MSI_FLAGS_ENABLE; 278 249 pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); 279 - } 280 - 281 - /* 282 - * Architecture override returns true when the PCI MSI message should be 283 - * written by the generic restore function. 284 - */ 285 - bool __weak arch_restore_msi_irqs(struct pci_dev *dev) 286 - { 287 - return true; 288 - } 289 - 290 - static void __pci_restore_msi_state(struct pci_dev *dev) 291 - { 292 - struct msi_desc *entry; 293 - u16 control; 294 - 295 - if (!dev->msi_enabled) 296 - return; 297 - 298 - entry = irq_get_msi_desc(dev->irq); 299 - 300 - pci_intx_for_msi(dev, 0); 301 - pci_msi_set_enable(dev, 0); 302 - if (arch_restore_msi_irqs(dev)) 303 - __pci_write_msi_msg(entry, &entry->msg); 304 - 305 - pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); 306 - pci_msi_update_mask(entry, 0, 0); 307 - control &= ~PCI_MSI_FLAGS_QSIZE; 308 - control |= (entry->pci.msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; 309 - pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); 310 - } 311 - 312 - static void pci_msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set) 313 - { 314 - u16 ctrl; 315 - 316 - pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl); 317 - ctrl &= ~clear; 318 - ctrl |= set; 319 - pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl); 320 - } 321 - 322 - static void __pci_restore_msix_state(struct pci_dev *dev) 323 - { 324 - struct msi_desc *entry; 325 - bool write_msg; 326 - 327 - if (!dev->msix_enabled) 328 - return; 329 - 330 - /* route the table */ 331 - pci_intx_for_msi(dev, 0); 332 - pci_msix_clear_and_set_ctrl(dev, 0, 333 - PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL); 334 - 335 - write_msg = arch_restore_msi_irqs(dev); 336 - 337 - msi_lock_descs(&dev->dev); 338 - msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 339 - if (write_msg) 340 - __pci_write_msi_msg(entry, &entry->msg); 341 - pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 342 - } 343 - msi_unlock_descs(&dev->dev); 344 - 345 - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 346 - } 347 - 348 - void pci_restore_msi_state(struct pci_dev *dev) 349 - { 350 - __pci_restore_msi_state(dev); 351 - __pci_restore_msix_state(dev); 352 - } 353 - EXPORT_SYMBOL_GPL(pci_restore_msi_state); 354 - 355 - static void pcim_msi_release(void *pcidev) 356 - { 357 - struct pci_dev *dev = pcidev; 358 - 359 - dev->is_msi_managed = false; 360 - pci_free_irq_vectors(dev); 361 - } 362 - 363 - /* 364 - * Needs to be separate from pcim_release to prevent an ordering problem 365 - * vs. msi_device_data_release() in the MSI core code. 366 - */ 367 - static int pcim_setup_msi_release(struct pci_dev *dev) 368 - { 369 - int ret; 370 - 371 - if (!pci_is_managed(dev) || dev->is_msi_managed) 372 - return 0; 373 - 374 - ret = devm_add_action(&dev->dev, pcim_msi_release, dev); 375 - if (!ret) 376 - dev->is_msi_managed = true; 377 - return ret; 378 - } 379 - 380 - /* 381 - * Ordering vs. devres: msi device data has to be installed first so that 382 - * pcim_msi_release() is invoked before it on device release. 383 - */ 384 - static int pci_setup_msi_context(struct pci_dev *dev) 385 - { 386 - int ret = msi_setup_device_data(&dev->dev); 387 - 388 - if (!ret) 389 - ret = pcim_setup_msi_release(dev); 390 - return ret; 391 250 } 392 251 393 252 static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, ··· 312 395 if (desc.pci.msi_attrib.can_mask) 313 396 pci_read_config_dword(dev, desc.pci.mask_pos, &desc.pci.msi_mask); 314 397 315 - return msi_add_msi_desc(&dev->dev, &desc); 398 + return msi_insert_msi_desc(&dev->dev, &desc); 316 399 } 317 400 318 401 static int msi_verify_entries(struct pci_dev *dev) ··· 350 433 struct irq_affinity_desc *masks = NULL; 351 434 struct msi_desc *entry; 352 435 int ret; 436 + 437 + /* Reject multi-MSI early on irq domain enabled architectures */ 438 + if (nvec > 1 && !pci_msi_domain_supports(dev, MSI_FLAG_MULTI_PCI_MSI, ALLOW_LEGACY)) 439 + return 1; 353 440 354 441 /* 355 442 * Disable MSI during setup in the hardware, but mark it enabled ··· 393 472 394 473 err: 395 474 pci_msi_unmask(entry, msi_multi_mask(entry)); 396 - free_msi_irqs(dev); 475 + pci_free_msi_irqs(dev); 397 476 fail: 398 477 dev->msi_enabled = 0; 399 478 unlock: ··· 402 481 return ret; 403 482 } 404 483 405 - static void __iomem *msix_map_region(struct pci_dev *dev, 406 - unsigned int nr_entries) 407 - { 408 - resource_size_t phys_addr; 409 - u32 table_offset; 410 - unsigned long flags; 411 - u8 bir; 412 - 413 - pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, 414 - &table_offset); 415 - bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); 416 - flags = pci_resource_flags(dev, bir); 417 - if (!flags || (flags & IORESOURCE_UNSET)) 418 - return NULL; 419 - 420 - table_offset &= PCI_MSIX_TABLE_OFFSET; 421 - phys_addr = pci_resource_start(dev, bir) + table_offset; 422 - 423 - return ioremap(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); 424 - } 425 - 426 - static int msix_setup_msi_descs(struct pci_dev *dev, void __iomem *base, 427 - struct msix_entry *entries, int nvec, 428 - struct irq_affinity_desc *masks) 429 - { 430 - int ret = 0, i, vec_count = pci_msix_vec_count(dev); 431 - struct irq_affinity_desc *curmsk; 432 - struct msi_desc desc; 433 - void __iomem *addr; 434 - 435 - memset(&desc, 0, sizeof(desc)); 436 - 437 - desc.nvec_used = 1; 438 - desc.pci.msi_attrib.is_msix = 1; 439 - desc.pci.msi_attrib.is_64 = 1; 440 - desc.pci.msi_attrib.default_irq = dev->irq; 441 - desc.pci.mask_base = base; 442 - 443 - for (i = 0, curmsk = masks; i < nvec; i++, curmsk++) { 444 - desc.msi_index = entries ? entries[i].entry : i; 445 - desc.affinity = masks ? curmsk : NULL; 446 - desc.pci.msi_attrib.is_virtual = desc.msi_index >= vec_count; 447 - desc.pci.msi_attrib.can_mask = !pci_msi_ignore_mask && 448 - !desc.pci.msi_attrib.is_virtual; 449 - 450 - if (desc.pci.msi_attrib.can_mask) { 451 - addr = pci_msix_desc_addr(&desc); 452 - desc.pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); 453 - } 454 - 455 - ret = msi_add_msi_desc(&dev->dev, &desc); 456 - if (ret) 457 - break; 458 - } 459 - return ret; 460 - } 461 - 462 - static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries) 463 - { 464 - struct msi_desc *desc; 465 - 466 - if (entries) { 467 - msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) { 468 - entries->vector = desc->irq; 469 - entries++; 470 - } 471 - } 472 - } 473 - 474 - static void msix_mask_all(void __iomem *base, int tsize) 475 - { 476 - u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT; 477 - int i; 478 - 479 - if (pci_msi_ignore_mask) 480 - return; 481 - 482 - for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE) 483 - writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); 484 - } 485 - 486 - static int msix_setup_interrupts(struct pci_dev *dev, void __iomem *base, 487 - struct msix_entry *entries, int nvec, 488 - struct irq_affinity *affd) 489 - { 490 - struct irq_affinity_desc *masks = NULL; 491 - int ret; 492 - 493 - if (affd) 494 - masks = irq_create_affinity_masks(nvec, affd); 495 - 496 - msi_lock_descs(&dev->dev); 497 - ret = msix_setup_msi_descs(dev, base, entries, nvec, masks); 498 - if (ret) 499 - goto out_free; 500 - 501 - ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 502 - if (ret) 503 - goto out_free; 504 - 505 - /* Check if all MSI entries honor device restrictions */ 506 - ret = msi_verify_entries(dev); 507 - if (ret) 508 - goto out_free; 509 - 510 - msix_update_entries(dev, entries); 511 - goto out_unlock; 512 - 513 - out_free: 514 - free_msi_irqs(dev); 515 - out_unlock: 516 - msi_unlock_descs(&dev->dev); 517 - kfree(masks); 518 - return ret; 519 - } 520 - 521 - /** 522 - * msix_capability_init - configure device's MSI-X capability 523 - * @dev: pointer to the pci_dev data structure of MSI-X device function 524 - * @entries: pointer to an array of struct msix_entry entries 525 - * @nvec: number of @entries 526 - * @affd: Optional pointer to enable automatic affinity assignment 527 - * 528 - * Setup the MSI-X capability structure of device function with a 529 - * single MSI-X IRQ. A return of zero indicates the successful setup of 530 - * requested MSI-X entries with allocated IRQs or non-zero for otherwise. 531 - **/ 532 - static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, 533 - int nvec, struct irq_affinity *affd) 534 - { 535 - void __iomem *base; 536 - int ret, tsize; 537 - u16 control; 538 - 539 - /* 540 - * Some devices require MSI-X to be enabled before the MSI-X 541 - * registers can be accessed. Mask all the vectors to prevent 542 - * interrupts coming in before they're fully set up. 543 - */ 544 - pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL | 545 - PCI_MSIX_FLAGS_ENABLE); 546 - 547 - /* Mark it enabled so setup functions can query it */ 548 - dev->msix_enabled = 1; 549 - 550 - pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); 551 - /* Request & Map MSI-X table region */ 552 - tsize = msix_table_size(control); 553 - base = msix_map_region(dev, tsize); 554 - if (!base) { 555 - ret = -ENOMEM; 556 - goto out_disable; 557 - } 558 - 559 - dev->msix_base = base; 560 - 561 - ret = msix_setup_interrupts(dev, base, entries, nvec, affd); 562 - if (ret) 563 - goto out_disable; 564 - 565 - /* Disable INTX */ 566 - pci_intx_for_msi(dev, 0); 567 - 568 - /* 569 - * Ensure that all table entries are masked to prevent 570 - * stale entries from firing in a crash kernel. 571 - * 572 - * Done late to deal with a broken Marvell NVME device 573 - * which takes the MSI-X mask bits into account even 574 - * when MSI-X is disabled, which prevents MSI delivery. 575 - */ 576 - msix_mask_all(base, tsize); 577 - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 578 - 579 - pcibios_free_irq(dev); 580 - return 0; 581 - 582 - out_disable: 583 - dev->msix_enabled = 0; 584 - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); 585 - 586 - return ret; 587 - } 588 - 589 - /** 590 - * pci_msi_supported - check whether MSI may be enabled on a device 591 - * @dev: pointer to the pci_dev data structure of MSI device function 592 - * @nvec: how many MSIs have been requested? 593 - * 594 - * Look at global flags, the device itself, and its parent buses 595 - * to determine if MSI/-X are supported for the device. If MSI/-X is 596 - * supported return 1, else return 0. 597 - **/ 598 - static int pci_msi_supported(struct pci_dev *dev, int nvec) 599 - { 600 - struct pci_bus *bus; 601 - 602 - /* MSI must be globally enabled and supported by the device */ 603 - if (!pci_msi_enable) 604 - return 0; 605 - 606 - if (!dev || dev->no_msi) 607 - return 0; 608 - 609 - /* 610 - * You can't ask to have 0 or less MSIs configured. 611 - * a) it's stupid .. 612 - * b) the list manipulation code assumes nvec >= 1. 613 - */ 614 - if (nvec < 1) 615 - return 0; 616 - 617 - /* 618 - * Any bridge which does NOT route MSI transactions from its 619 - * secondary bus to its primary bus must set NO_MSI flag on 620 - * the secondary pci_bus. 621 - * 622 - * The NO_MSI flag can either be set directly by: 623 - * - arch-specific PCI host bus controller drivers (deprecated) 624 - * - quirks for specific PCI bridges 625 - * 626 - * or indirectly by platform-specific PCI host bridge drivers by 627 - * advertising the 'msi_domain' property, which results in 628 - * the NO_MSI flag when no MSI domain is found for this bridge 629 - * at probe time. 630 - */ 631 - for (bus = dev->bus; bus; bus = bus->parent) 632 - if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 633 - return 0; 634 - 635 - return 1; 636 - } 637 - 638 - /** 639 - * pci_msi_vec_count - Return the number of MSI vectors a device can send 640 - * @dev: device to report about 641 - * 642 - * This function returns the number of MSI vectors a device requested via 643 - * Multiple Message Capable register. It returns a negative errno if the 644 - * device is not capable sending MSI interrupts. Otherwise, the call succeeds 645 - * and returns a power of two, up to a maximum of 2^5 (32), according to the 646 - * MSI specification. 647 - **/ 648 - int pci_msi_vec_count(struct pci_dev *dev) 649 - { 650 - int ret; 651 - u16 msgctl; 652 - 653 - if (!dev->msi_cap) 654 - return -EINVAL; 655 - 656 - pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); 657 - ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); 658 - 659 - return ret; 660 - } 661 - EXPORT_SYMBOL(pci_msi_vec_count); 662 - 663 - static void pci_msi_shutdown(struct pci_dev *dev) 664 - { 665 - struct msi_desc *desc; 666 - 667 - if (!pci_msi_enable || !dev || !dev->msi_enabled) 668 - return; 669 - 670 - pci_msi_set_enable(dev, 0); 671 - pci_intx_for_msi(dev, 1); 672 - dev->msi_enabled = 0; 673 - 674 - /* Return the device with MSI unmasked as initial states */ 675 - desc = msi_first_desc(&dev->dev, MSI_DESC_ALL); 676 - if (!WARN_ON_ONCE(!desc)) 677 - pci_msi_unmask(desc, msi_multi_mask(desc)); 678 - 679 - /* Restore dev->irq to its default pin-assertion IRQ */ 680 - dev->irq = desc->pci.msi_attrib.default_irq; 681 - pcibios_alloc_irq(dev); 682 - } 683 - 684 - void pci_disable_msi(struct pci_dev *dev) 685 - { 686 - if (!pci_msi_enable || !dev || !dev->msi_enabled) 687 - return; 688 - 689 - msi_lock_descs(&dev->dev); 690 - pci_msi_shutdown(dev); 691 - free_msi_irqs(dev); 692 - msi_unlock_descs(&dev->dev); 693 - } 694 - EXPORT_SYMBOL(pci_disable_msi); 695 - 696 - /** 697 - * pci_msix_vec_count - return the number of device's MSI-X table entries 698 - * @dev: pointer to the pci_dev data structure of MSI-X device function 699 - * This function returns the number of device's MSI-X table entries and 700 - * therefore the number of MSI-X vectors device is capable of sending. 701 - * It returns a negative errno if the device is not capable of sending MSI-X 702 - * interrupts. 703 - **/ 704 - int pci_msix_vec_count(struct pci_dev *dev) 705 - { 706 - u16 control; 707 - 708 - if (!dev->msix_cap) 709 - return -EINVAL; 710 - 711 - pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); 712 - return msix_table_size(control); 713 - } 714 - EXPORT_SYMBOL(pci_msix_vec_count); 715 - 716 - static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, 717 - int nvec, struct irq_affinity *affd, int flags) 718 - { 719 - int nr_entries; 720 - int i, j; 721 - 722 - if (!pci_msi_supported(dev, nvec) || dev->current_state != PCI_D0) 723 - return -EINVAL; 724 - 725 - nr_entries = pci_msix_vec_count(dev); 726 - if (nr_entries < 0) 727 - return nr_entries; 728 - if (nvec > nr_entries && !(flags & PCI_IRQ_VIRTUAL)) 729 - return nr_entries; 730 - 731 - if (entries) { 732 - /* Check for any invalid entries */ 733 - for (i = 0; i < nvec; i++) { 734 - if (entries[i].entry >= nr_entries) 735 - return -EINVAL; /* invalid entry */ 736 - for (j = i + 1; j < nvec; j++) { 737 - if (entries[i].entry == entries[j].entry) 738 - return -EINVAL; /* duplicate entry */ 739 - } 740 - } 741 - } 742 - 743 - /* Check whether driver already requested for MSI IRQ */ 744 - if (dev->msi_enabled) { 745 - pci_info(dev, "can't enable MSI-X (MSI IRQ already assigned)\n"); 746 - return -EINVAL; 747 - } 748 - return msix_capability_init(dev, entries, nvec, affd); 749 - } 750 - 751 - static void pci_msix_shutdown(struct pci_dev *dev) 752 - { 753 - struct msi_desc *desc; 754 - 755 - if (!pci_msi_enable || !dev || !dev->msix_enabled) 756 - return; 757 - 758 - if (pci_dev_is_disconnected(dev)) { 759 - dev->msix_enabled = 0; 760 - return; 761 - } 762 - 763 - /* Return the device with MSI-X masked as initial states */ 764 - msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) 765 - pci_msix_mask(desc); 766 - 767 - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); 768 - pci_intx_for_msi(dev, 1); 769 - dev->msix_enabled = 0; 770 - pcibios_alloc_irq(dev); 771 - } 772 - 773 - void pci_disable_msix(struct pci_dev *dev) 774 - { 775 - if (!pci_msi_enable || !dev || !dev->msix_enabled) 776 - return; 777 - 778 - msi_lock_descs(&dev->dev); 779 - pci_msix_shutdown(dev); 780 - free_msi_irqs(dev); 781 - msi_unlock_descs(&dev->dev); 782 - } 783 - EXPORT_SYMBOL(pci_disable_msix); 784 - 785 - static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, 786 - struct irq_affinity *affd) 484 + int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, 485 + struct irq_affinity *affd) 787 486 { 788 487 int nvec; 789 488 int rc; ··· 436 895 if (rc) 437 896 return rc; 438 897 898 + if (!pci_setup_msi_device_domain(dev)) 899 + return -ENODEV; 900 + 439 901 for (;;) { 440 902 if (affd) { 441 903 nvec = irq_calc_affinity_vectors(minvec, nvec, affd); ··· 459 915 } 460 916 } 461 917 462 - /* deprecated, don't use */ 463 - int pci_enable_msi(struct pci_dev *dev) 918 + /** 919 + * pci_msi_vec_count - Return the number of MSI vectors a device can send 920 + * @dev: device to report about 921 + * 922 + * This function returns the number of MSI vectors a device requested via 923 + * Multiple Message Capable register. It returns a negative errno if the 924 + * device is not capable sending MSI interrupts. Otherwise, the call succeeds 925 + * and returns a power of two, up to a maximum of 2^5 (32), according to the 926 + * MSI specification. 927 + **/ 928 + int pci_msi_vec_count(struct pci_dev *dev) 464 929 { 465 - int rc = __pci_enable_msi_range(dev, 1, 1, NULL); 466 - if (rc < 0) 467 - return rc; 468 - return 0; 469 - } 470 - EXPORT_SYMBOL(pci_enable_msi); 930 + int ret; 931 + u16 msgctl; 471 932 472 - static int __pci_enable_msix_range(struct pci_dev *dev, 473 - struct msix_entry *entries, int minvec, 474 - int maxvec, struct irq_affinity *affd, 475 - int flags) 933 + if (!dev->msi_cap) 934 + return -EINVAL; 935 + 936 + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); 937 + ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); 938 + 939 + return ret; 940 + } 941 + EXPORT_SYMBOL(pci_msi_vec_count); 942 + 943 + /* 944 + * Architecture override returns true when the PCI MSI message should be 945 + * written by the generic restore function. 946 + */ 947 + bool __weak arch_restore_msi_irqs(struct pci_dev *dev) 476 948 { 477 - int rc, nvec = maxvec; 949 + return true; 950 + } 951 + 952 + void __pci_restore_msi_state(struct pci_dev *dev) 953 + { 954 + struct msi_desc *entry; 955 + u16 control; 956 + 957 + if (!dev->msi_enabled) 958 + return; 959 + 960 + entry = irq_get_msi_desc(dev->irq); 961 + 962 + pci_intx_for_msi(dev, 0); 963 + pci_msi_set_enable(dev, 0); 964 + if (arch_restore_msi_irqs(dev)) 965 + __pci_write_msi_msg(entry, &entry->msg); 966 + 967 + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); 968 + pci_msi_update_mask(entry, 0, 0); 969 + control &= ~PCI_MSI_FLAGS_QSIZE; 970 + control |= (entry->pci.msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; 971 + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); 972 + } 973 + 974 + void pci_msi_shutdown(struct pci_dev *dev) 975 + { 976 + struct msi_desc *desc; 977 + 978 + if (!pci_msi_enable || !dev || !dev->msi_enabled) 979 + return; 980 + 981 + pci_msi_set_enable(dev, 0); 982 + pci_intx_for_msi(dev, 1); 983 + dev->msi_enabled = 0; 984 + 985 + /* Return the device with MSI unmasked as initial states */ 986 + desc = msi_first_desc(&dev->dev, MSI_DESC_ALL); 987 + if (!WARN_ON_ONCE(!desc)) 988 + pci_msi_unmask(desc, msi_multi_mask(desc)); 989 + 990 + /* Restore dev->irq to its default pin-assertion IRQ */ 991 + dev->irq = desc->pci.msi_attrib.default_irq; 992 + pcibios_alloc_irq(dev); 993 + } 994 + 995 + /* PCI/MSI-X specific functionality */ 996 + 997 + static void pci_msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set) 998 + { 999 + u16 ctrl; 1000 + 1001 + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl); 1002 + ctrl &= ~clear; 1003 + ctrl |= set; 1004 + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl); 1005 + } 1006 + 1007 + static void __iomem *msix_map_region(struct pci_dev *dev, 1008 + unsigned int nr_entries) 1009 + { 1010 + resource_size_t phys_addr; 1011 + u32 table_offset; 1012 + unsigned long flags; 1013 + u8 bir; 1014 + 1015 + pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, 1016 + &table_offset); 1017 + bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); 1018 + flags = pci_resource_flags(dev, bir); 1019 + if (!flags || (flags & IORESOURCE_UNSET)) 1020 + return NULL; 1021 + 1022 + table_offset &= PCI_MSIX_TABLE_OFFSET; 1023 + phys_addr = pci_resource_start(dev, bir) + table_offset; 1024 + 1025 + return ioremap(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); 1026 + } 1027 + 1028 + /** 1029 + * msix_prepare_msi_desc - Prepare a half initialized MSI descriptor for operation 1030 + * @dev: The PCI device for which the descriptor is prepared 1031 + * @desc: The MSI descriptor for preparation 1032 + * 1033 + * This is separate from msix_setup_msi_descs() below to handle dynamic 1034 + * allocations for MSI-X after initial enablement. 1035 + * 1036 + * Ideally the whole MSI-X setup would work that way, but there is no way to 1037 + * support this for the legacy arch_setup_msi_irqs() mechanism and for the 1038 + * fake irq domains like the x86 XEN one. Sigh... 1039 + * 1040 + * The descriptor is zeroed and only @desc::msi_index and @desc::affinity 1041 + * are set. When called from msix_setup_msi_descs() then the is_virtual 1042 + * attribute is initialized as well. 1043 + * 1044 + * Fill in the rest. 1045 + */ 1046 + void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc) 1047 + { 1048 + desc->nvec_used = 1; 1049 + desc->pci.msi_attrib.is_msix = 1; 1050 + desc->pci.msi_attrib.is_64 = 1; 1051 + desc->pci.msi_attrib.default_irq = dev->irq; 1052 + desc->pci.mask_base = dev->msix_base; 1053 + desc->pci.msi_attrib.can_mask = !pci_msi_ignore_mask && 1054 + !desc->pci.msi_attrib.is_virtual; 1055 + 1056 + if (desc->pci.msi_attrib.can_mask) { 1057 + void __iomem *addr = pci_msix_desc_addr(desc); 1058 + 1059 + desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); 1060 + } 1061 + } 1062 + 1063 + static int msix_setup_msi_descs(struct pci_dev *dev, struct msix_entry *entries, 1064 + int nvec, struct irq_affinity_desc *masks) 1065 + { 1066 + int ret = 0, i, vec_count = pci_msix_vec_count(dev); 1067 + struct irq_affinity_desc *curmsk; 1068 + struct msi_desc desc; 1069 + 1070 + memset(&desc, 0, sizeof(desc)); 1071 + 1072 + for (i = 0, curmsk = masks; i < nvec; i++, curmsk++) { 1073 + desc.msi_index = entries ? entries[i].entry : i; 1074 + desc.affinity = masks ? curmsk : NULL; 1075 + desc.pci.msi_attrib.is_virtual = desc.msi_index >= vec_count; 1076 + 1077 + msix_prepare_msi_desc(dev, &desc); 1078 + 1079 + ret = msi_insert_msi_desc(&dev->dev, &desc); 1080 + if (ret) 1081 + break; 1082 + } 1083 + return ret; 1084 + } 1085 + 1086 + static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries) 1087 + { 1088 + struct msi_desc *desc; 1089 + 1090 + if (entries) { 1091 + msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) { 1092 + entries->vector = desc->irq; 1093 + entries++; 1094 + } 1095 + } 1096 + } 1097 + 1098 + static void msix_mask_all(void __iomem *base, int tsize) 1099 + { 1100 + u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT; 1101 + int i; 1102 + 1103 + if (pci_msi_ignore_mask) 1104 + return; 1105 + 1106 + for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE) 1107 + writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); 1108 + } 1109 + 1110 + static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 1111 + int nvec, struct irq_affinity *affd) 1112 + { 1113 + struct irq_affinity_desc *masks = NULL; 1114 + int ret; 1115 + 1116 + if (affd) 1117 + masks = irq_create_affinity_masks(nvec, affd); 1118 + 1119 + msi_lock_descs(&dev->dev); 1120 + ret = msix_setup_msi_descs(dev, entries, nvec, masks); 1121 + if (ret) 1122 + goto out_free; 1123 + 1124 + ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 1125 + if (ret) 1126 + goto out_free; 1127 + 1128 + /* Check if all MSI entries honor device restrictions */ 1129 + ret = msi_verify_entries(dev); 1130 + if (ret) 1131 + goto out_free; 1132 + 1133 + msix_update_entries(dev, entries); 1134 + goto out_unlock; 1135 + 1136 + out_free: 1137 + pci_free_msi_irqs(dev); 1138 + out_unlock: 1139 + msi_unlock_descs(&dev->dev); 1140 + kfree(masks); 1141 + return ret; 1142 + } 1143 + 1144 + /** 1145 + * msix_capability_init - configure device's MSI-X capability 1146 + * @dev: pointer to the pci_dev data structure of MSI-X device function 1147 + * @entries: pointer to an array of struct msix_entry entries 1148 + * @nvec: number of @entries 1149 + * @affd: Optional pointer to enable automatic affinity assignment 1150 + * 1151 + * Setup the MSI-X capability structure of device function with a 1152 + * single MSI-X IRQ. A return of zero indicates the successful setup of 1153 + * requested MSI-X entries with allocated IRQs or non-zero for otherwise. 1154 + **/ 1155 + static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, 1156 + int nvec, struct irq_affinity *affd) 1157 + { 1158 + int ret, tsize; 1159 + u16 control; 1160 + 1161 + /* 1162 + * Some devices require MSI-X to be enabled before the MSI-X 1163 + * registers can be accessed. Mask all the vectors to prevent 1164 + * interrupts coming in before they're fully set up. 1165 + */ 1166 + pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL | 1167 + PCI_MSIX_FLAGS_ENABLE); 1168 + 1169 + /* Mark it enabled so setup functions can query it */ 1170 + dev->msix_enabled = 1; 1171 + 1172 + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); 1173 + /* Request & Map MSI-X table region */ 1174 + tsize = msix_table_size(control); 1175 + dev->msix_base = msix_map_region(dev, tsize); 1176 + if (!dev->msix_base) { 1177 + ret = -ENOMEM; 1178 + goto out_disable; 1179 + } 1180 + 1181 + ret = msix_setup_interrupts(dev, entries, nvec, affd); 1182 + if (ret) 1183 + goto out_disable; 1184 + 1185 + /* Disable INTX */ 1186 + pci_intx_for_msi(dev, 0); 1187 + 1188 + /* 1189 + * Ensure that all table entries are masked to prevent 1190 + * stale entries from firing in a crash kernel. 1191 + * 1192 + * Done late to deal with a broken Marvell NVME device 1193 + * which takes the MSI-X mask bits into account even 1194 + * when MSI-X is disabled, which prevents MSI delivery. 1195 + */ 1196 + msix_mask_all(dev->msix_base, tsize); 1197 + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 1198 + 1199 + pcibios_free_irq(dev); 1200 + return 0; 1201 + 1202 + out_disable: 1203 + dev->msix_enabled = 0; 1204 + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); 1205 + 1206 + return ret; 1207 + } 1208 + 1209 + static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries, 1210 + int nvec, int hwsize) 1211 + { 1212 + bool nogap; 1213 + int i, j; 1214 + 1215 + if (!entries) 1216 + return true; 1217 + 1218 + nogap = pci_msi_domain_supports(dev, MSI_FLAG_MSIX_CONTIGUOUS, DENY_LEGACY); 1219 + 1220 + for (i = 0; i < nvec; i++) { 1221 + /* Entry within hardware limit? */ 1222 + if (entries[i].entry >= hwsize) 1223 + return false; 1224 + 1225 + /* Check for duplicate entries */ 1226 + for (j = i + 1; j < nvec; j++) { 1227 + if (entries[i].entry == entries[j].entry) 1228 + return false; 1229 + } 1230 + /* Check for unsupported gaps */ 1231 + if (nogap && entries[i].entry != i) 1232 + return false; 1233 + } 1234 + return true; 1235 + } 1236 + 1237 + int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, 1238 + int maxvec, struct irq_affinity *affd, int flags) 1239 + { 1240 + int hwsize, rc, nvec = maxvec; 478 1241 479 1242 if (maxvec < minvec) 480 1243 return -ERANGE; 481 1244 1245 + if (dev->msi_enabled) { 1246 + pci_info(dev, "can't enable MSI-X (MSI already enabled)\n"); 1247 + return -EINVAL; 1248 + } 1249 + 482 1250 if (WARN_ON_ONCE(dev->msix_enabled)) 483 1251 return -EINVAL; 1252 + 1253 + /* Check MSI-X early on irq domain enabled architectures */ 1254 + if (!pci_msi_domain_supports(dev, MSI_FLAG_PCI_MSIX, ALLOW_LEGACY)) 1255 + return -ENOTSUPP; 1256 + 1257 + if (!pci_msi_supported(dev, nvec) || dev->current_state != PCI_D0) 1258 + return -EINVAL; 1259 + 1260 + hwsize = pci_msix_vec_count(dev); 1261 + if (hwsize < 0) 1262 + return hwsize; 1263 + 1264 + if (!pci_msix_validate_entries(dev, entries, nvec, hwsize)) 1265 + return -EINVAL; 1266 + 1267 + if (hwsize < nvec) { 1268 + /* Keep the IRQ virtual hackery working */ 1269 + if (flags & PCI_IRQ_VIRTUAL) 1270 + hwsize = nvec; 1271 + else 1272 + nvec = hwsize; 1273 + } 1274 + 1275 + if (nvec < minvec) 1276 + return -ENOSPC; 484 1277 485 1278 rc = pci_setup_msi_context(dev); 486 1279 if (rc) 487 1280 return rc; 1281 + 1282 + if (!pci_setup_msix_device_domain(dev, hwsize)) 1283 + return -ENODEV; 488 1284 489 1285 for (;;) { 490 1286 if (affd) { ··· 833 949 return -ENOSPC; 834 950 } 835 951 836 - rc = __pci_enable_msix(dev, entries, nvec, affd, flags); 952 + rc = msix_capability_init(dev, entries, nvec, affd); 837 953 if (rc == 0) 838 954 return nvec; 839 955 ··· 846 962 } 847 963 } 848 964 849 - /** 850 - * pci_enable_msix_range - configure device's MSI-X capability structure 851 - * @dev: pointer to the pci_dev data structure of MSI-X device function 852 - * @entries: pointer to an array of MSI-X entries 853 - * @minvec: minimum number of MSI-X IRQs requested 854 - * @maxvec: maximum number of MSI-X IRQs requested 855 - * 856 - * Setup the MSI-X capability structure of device function with a maximum 857 - * possible number of interrupts in the range between @minvec and @maxvec 858 - * upon its software driver call to request for MSI-X mode enabled on its 859 - * hardware device function. It returns a negative errno if an error occurs. 860 - * If it succeeds, it returns the actual number of interrupts allocated and 861 - * indicates the successful configuration of MSI-X capability structure 862 - * with new allocated MSI-X interrupts. 863 - **/ 864 - int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, 865 - int minvec, int maxvec) 965 + void __pci_restore_msix_state(struct pci_dev *dev) 866 966 { 867 - return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL, 0); 868 - } 869 - EXPORT_SYMBOL(pci_enable_msix_range); 967 + struct msi_desc *entry; 968 + bool write_msg; 870 969 871 - /** 872 - * pci_alloc_irq_vectors_affinity - allocate multiple IRQs for a device 873 - * @dev: PCI device to operate on 874 - * @min_vecs: minimum number of vectors required (must be >= 1) 875 - * @max_vecs: maximum (desired) number of vectors 876 - * @flags: flags or quirks for the allocation 877 - * @affd: optional description of the affinity requirements 878 - * 879 - * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI 880 - * vectors if available, and fall back to a single legacy vector 881 - * if neither is available. Return the number of vectors allocated, 882 - * (which might be smaller than @max_vecs) if successful, or a negative 883 - * error code on error. If less than @min_vecs interrupt vectors are 884 - * available for @dev the function will fail with -ENOSPC. 885 - * 886 - * To get the Linux IRQ number used for a vector that can be passed to 887 - * request_irq() use the pci_irq_vector() helper. 888 - */ 889 - int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, 890 - unsigned int max_vecs, unsigned int flags, 891 - struct irq_affinity *affd) 892 - { 893 - struct irq_affinity msi_default_affd = {0}; 894 - int nvecs = -ENOSPC; 970 + if (!dev->msix_enabled) 971 + return; 895 972 896 - if (flags & PCI_IRQ_AFFINITY) { 897 - if (!affd) 898 - affd = &msi_default_affd; 899 - } else { 900 - if (WARN_ON(affd)) 901 - affd = NULL; 973 + /* route the table */ 974 + pci_intx_for_msi(dev, 0); 975 + pci_msix_clear_and_set_ctrl(dev, 0, 976 + PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL); 977 + 978 + write_msg = arch_restore_msi_irqs(dev); 979 + 980 + msi_lock_descs(&dev->dev); 981 + msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 982 + if (write_msg) 983 + __pci_write_msi_msg(entry, &entry->msg); 984 + pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 902 985 } 986 + msi_unlock_descs(&dev->dev); 903 987 904 - if (flags & PCI_IRQ_MSIX) { 905 - nvecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, 906 - affd, flags); 907 - if (nvecs > 0) 908 - return nvecs; 909 - } 910 - 911 - if (flags & PCI_IRQ_MSI) { 912 - nvecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd); 913 - if (nvecs > 0) 914 - return nvecs; 915 - } 916 - 917 - /* use legacy IRQ if allowed */ 918 - if (flags & PCI_IRQ_LEGACY) { 919 - if (min_vecs == 1 && dev->irq) { 920 - /* 921 - * Invoke the affinity spreading logic to ensure that 922 - * the device driver can adjust queue configuration 923 - * for the single interrupt case. 924 - */ 925 - if (affd) 926 - irq_create_affinity_masks(1, affd); 927 - pci_intx(dev, 1); 928 - return 1; 929 - } 930 - } 931 - 932 - return nvecs; 988 + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 933 989 } 934 - EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity); 935 990 936 - /** 937 - * pci_free_irq_vectors - free previously allocated IRQs for a device 938 - * @dev: PCI device to operate on 939 - * 940 - * Undoes the allocations and enabling in pci_alloc_irq_vectors(). 941 - */ 942 - void pci_free_irq_vectors(struct pci_dev *dev) 991 + void pci_msix_shutdown(struct pci_dev *dev) 943 992 { 944 - pci_disable_msix(dev); 945 - pci_disable_msi(dev); 946 - } 947 - EXPORT_SYMBOL(pci_free_irq_vectors); 948 - 949 - /** 950 - * pci_irq_vector - return Linux IRQ number of a device vector 951 - * @dev: PCI device to operate on 952 - * @nr: Interrupt vector index (0-based) 953 - * 954 - * @nr has the following meanings depending on the interrupt mode: 955 - * MSI-X: The index in the MSI-X vector table 956 - * MSI: The index of the enabled MSI vectors 957 - * INTx: Must be 0 958 - * 959 - * Return: The Linux interrupt number or -EINVAl if @nr is out of range. 960 - */ 961 - int pci_irq_vector(struct pci_dev *dev, unsigned int nr) 962 - { 963 - unsigned int irq; 964 - 965 - if (!dev->msi_enabled && !dev->msix_enabled) 966 - return !nr ? dev->irq : -EINVAL; 967 - 968 - irq = msi_get_virq(&dev->dev, nr); 969 - return irq ? irq : -EINVAL; 970 - } 971 - EXPORT_SYMBOL(pci_irq_vector); 972 - 973 - /** 974 - * pci_irq_get_affinity - return the affinity of a particular MSI vector 975 - * @dev: PCI device to operate on 976 - * @nr: device-relative interrupt vector index (0-based). 977 - * 978 - * @nr has the following meanings depending on the interrupt mode: 979 - * MSI-X: The index in the MSI-X vector table 980 - * MSI: The index of the enabled MSI vectors 981 - * INTx: Must be 0 982 - * 983 - * Return: A cpumask pointer or NULL if @nr is out of range 984 - */ 985 - const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) 986 - { 987 - int idx, irq = pci_irq_vector(dev, nr); 988 993 struct msi_desc *desc; 989 994 990 - if (WARN_ON_ONCE(irq <= 0)) 991 - return NULL; 995 + if (!pci_msi_enable || !dev || !dev->msix_enabled) 996 + return; 992 997 993 - desc = irq_get_msi_desc(irq); 994 - /* Non-MSI does not have the information handy */ 995 - if (!desc) 996 - return cpu_possible_mask; 998 + if (pci_dev_is_disconnected(dev)) { 999 + dev->msix_enabled = 0; 1000 + return; 1001 + } 997 1002 998 - /* MSI[X] interrupts can be allocated without affinity descriptor */ 999 - if (!desc->affinity) 1000 - return NULL; 1003 + /* Return the device with MSI-X masked as initial states */ 1004 + msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) 1005 + pci_msix_mask(desc); 1001 1006 1002 - /* 1003 - * MSI has a mask array in the descriptor. 1004 - * MSI-X has a single mask. 1005 - */ 1006 - idx = dev->msi_enabled ? nr : 0; 1007 - return &desc->affinity[idx].mask; 1007 + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); 1008 + pci_intx_for_msi(dev, 1); 1009 + dev->msix_enabled = 0; 1010 + pcibios_alloc_irq(dev); 1008 1011 } 1009 - EXPORT_SYMBOL(pci_irq_get_affinity); 1012 + 1013 + /* Common interfaces */ 1014 + 1015 + void pci_free_msi_irqs(struct pci_dev *dev) 1016 + { 1017 + pci_msi_teardown_msi_irqs(dev); 1018 + 1019 + if (dev->msix_base) { 1020 + iounmap(dev->msix_base); 1021 + dev->msix_base = NULL; 1022 + } 1023 + } 1024 + 1025 + /* Misc. infrastructure */ 1010 1026 1011 1027 struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc) 1012 1028 { ··· 918 1134 { 919 1135 pci_msi_enable = 0; 920 1136 } 921 - 922 - /** 923 - * pci_msi_enabled - is MSI enabled? 924 - * 925 - * Returns true if MSI has not been disabled by the command-line option 926 - * pci=nomsi. 927 - **/ 928 - int pci_msi_enabled(void) 929 - { 930 - return pci_msi_enable; 931 - } 932 - EXPORT_SYMBOL(pci_msi_enabled);
+102 -12
drivers/pci/msi/msi.h
··· 5 5 6 6 #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) 7 7 8 - extern int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 9 - extern void pci_msi_teardown_msi_irqs(struct pci_dev *dev); 8 + int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 9 + void pci_msi_teardown_msi_irqs(struct pci_dev *dev); 10 10 11 - #ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS 12 - extern int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 13 - extern void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev); 14 - #else 15 - static inline int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 11 + /* Mask/unmask helpers */ 12 + void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 set); 13 + 14 + static inline void pci_msi_mask(struct msi_desc *desc, u32 mask) 16 15 { 17 - WARN_ON_ONCE(1); 18 - return -ENODEV; 16 + pci_msi_update_mask(desc, 0, mask); 19 17 } 20 18 21 - static inline void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev) 19 + static inline void pci_msi_unmask(struct msi_desc *desc, u32 mask) 22 20 { 23 - WARN_ON_ONCE(1); 21 + pci_msi_update_mask(desc, mask, 0); 24 22 } 25 - #endif 23 + 24 + static inline void __iomem *pci_msix_desc_addr(struct msi_desc *desc) 25 + { 26 + return desc->pci.mask_base + desc->msi_index * PCI_MSIX_ENTRY_SIZE; 27 + } 28 + 29 + /* 30 + * This internal function does not flush PCI writes to the device. All 31 + * users must ensure that they read from the device before either assuming 32 + * that the device state is up to date, or returning out of this file. 33 + * It does not affect the msi_desc::msix_ctrl cache either. Use with care! 34 + */ 35 + static inline void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl) 36 + { 37 + void __iomem *desc_addr = pci_msix_desc_addr(desc); 38 + 39 + if (desc->pci.msi_attrib.can_mask) 40 + writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); 41 + } 42 + 43 + static inline void pci_msix_mask(struct msi_desc *desc) 44 + { 45 + desc->pci.msix_ctrl |= PCI_MSIX_ENTRY_CTRL_MASKBIT; 46 + pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 47 + /* Flush write to device */ 48 + readl(desc->pci.mask_base); 49 + } 50 + 51 + static inline void pci_msix_unmask(struct msi_desc *desc) 52 + { 53 + desc->pci.msix_ctrl &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; 54 + pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 55 + } 56 + 57 + static inline void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask) 58 + { 59 + if (desc->pci.msi_attrib.is_msix) 60 + pci_msix_mask(desc); 61 + else 62 + pci_msi_mask(desc, mask); 63 + } 64 + 65 + static inline void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask) 66 + { 67 + if (desc->pci.msi_attrib.is_msix) 68 + pci_msix_unmask(desc); 69 + else 70 + pci_msi_unmask(desc, mask); 71 + } 26 72 27 73 /* 28 74 * PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to ··· 83 37 return 0xffffffff; 84 38 return (1 << (1 << desc->pci.msi_attrib.multi_cap)) - 1; 85 39 } 40 + 41 + void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc); 42 + 43 + /* Subsystem variables */ 44 + extern int pci_msi_enable; 45 + 46 + /* MSI internal functions invoked from the public APIs */ 47 + void pci_msi_shutdown(struct pci_dev *dev); 48 + void pci_msix_shutdown(struct pci_dev *dev); 49 + void pci_free_msi_irqs(struct pci_dev *dev); 50 + int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, struct irq_affinity *affd); 51 + int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, 52 + int maxvec, struct irq_affinity *affd, int flags); 53 + void __pci_restore_msi_state(struct pci_dev *dev); 54 + void __pci_restore_msix_state(struct pci_dev *dev); 55 + 56 + /* irq_domain related functionality */ 57 + 58 + enum support_mode { 59 + ALLOW_LEGACY, 60 + DENY_LEGACY, 61 + }; 62 + 63 + bool pci_msi_domain_supports(struct pci_dev *dev, unsigned int feature_mask, enum support_mode mode); 64 + bool pci_setup_msi_device_domain(struct pci_dev *pdev); 65 + bool pci_setup_msix_device_domain(struct pci_dev *pdev, unsigned int hwsize); 66 + 67 + /* Legacy (!IRQDOMAIN) fallbacks */ 68 + 69 + #ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS 70 + int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 71 + void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev); 72 + #else 73 + static inline int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 74 + { 75 + WARN_ON_ONCE(1); 76 + return -ENODEV; 77 + } 78 + 79 + static inline void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev) 80 + { 81 + WARN_ON_ONCE(1); 82 + } 83 + #endif
-2
drivers/pci/probe.c
··· 842 842 if (!d) 843 843 d = pci_host_bridge_acpi_msi_domain(bus); 844 844 845 - #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 846 845 /* 847 846 * If no IRQ domain was found via the OF tree, try looking it up 848 847 * directly through the fwnode_handle. ··· 853 854 d = irq_find_matching_fwnode(fwnode, 854 855 DOMAIN_BUS_PCI_MSI); 855 856 } 856 - #endif 857 857 858 858 return d; 859 859 }
+1 -1
drivers/perf/Kconfig
··· 93 93 config ARM_SMMU_V3_PMU 94 94 tristate "ARM SMMUv3 Performance Monitors Extension" 95 95 depends on (ARM64 && ACPI) || (COMPILE_TEST && 64BIT) 96 - depends on GENERIC_MSI_IRQ_DOMAIN 96 + depends on GENERIC_MSI_IRQ 97 97 help 98 98 Provides support for the ARM SMMUv3 Performance Monitor Counter 99 99 Groups (PMCG), which provide monitoring of transactions passing
-1
drivers/soc/fsl/dpio/dpio-driver.c
··· 10 10 #include <linux/module.h> 11 11 #include <linux/platform_device.h> 12 12 #include <linux/interrupt.h> 13 - #include <linux/msi.h> 14 13 #include <linux/dma-mapping.h> 15 14 #include <linux/delay.h> 16 15 #include <linux/io.h>
+1 -1
drivers/soc/ti/Kconfig
··· 98 98 99 99 config TI_SCI_INTA_MSI_DOMAIN 100 100 bool 101 - select GENERIC_MSI_IRQ_DOMAIN 101 + select GENERIC_MSI_IRQ 102 102 help 103 103 Driver to enable Interrupt Aggregator specific MSI Domain.
+4 -8
drivers/soc/ti/ti_sci_inta_msi.c
··· 73 73 for (set = 0; set < res->sets; set++) { 74 74 for (i = 0; i < res->desc[set].num; i++, count++) { 75 75 msi_desc.msi_index = res->desc[set].start + i; 76 - if (msi_add_msi_desc(dev, &msi_desc)) 76 + if (msi_insert_msi_desc(dev, &msi_desc)) 77 77 goto fail; 78 78 } 79 79 80 80 for (i = 0; i < res->desc[set].num_sec; i++, count++) { 81 81 msi_desc.msi_index = res->desc[set].start_sec + i; 82 - if (msi_add_msi_desc(dev, &msi_desc)) 82 + if (msi_insert_msi_desc(dev, &msi_desc)) 83 83 goto fail; 84 84 } 85 85 } ··· 93 93 struct ti_sci_resource *res) 94 94 { 95 95 struct platform_device *pdev = to_platform_device(dev); 96 - struct irq_domain *msi_domain; 97 96 int ret, nvec; 98 - 99 - msi_domain = dev_get_msi_domain(dev); 100 - if (!msi_domain) 101 - return -EINVAL; 102 97 103 98 if (pdev->id < 0) 104 99 return -ENODEV; ··· 109 114 goto unlock; 110 115 } 111 116 112 - ret = msi_domain_alloc_irqs_descs_locked(msi_domain, dev, nvec); 117 + /* Use alloc ALL as it's unclear whether there are gaps in the indices */ 118 + ret = msi_domain_alloc_irqs_all_locked(dev, MSI_DEFAULT_DOMAIN, nvec); 113 119 if (ret) 114 120 dev_err(dev, "Failed to allocate IRQs %d\n", ret); 115 121 unlock:
-1
drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
··· 8 8 #include <linux/slab.h> 9 9 #include <linux/types.h> 10 10 #include <linux/eventfd.h> 11 - #include <linux/msi.h> 12 11 13 12 #include "linux/fsl/mc.h" 14 13 #include "vfio_fsl_mc_private.h"
+2 -2
include/asm-generic/msi.h
··· 4 4 5 5 #include <linux/types.h> 6 6 7 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 7 + #ifdef CONFIG_GENERIC_MSI_IRQ 8 8 9 9 #ifndef NUM_MSI_ALLOC_SCRATCHPAD_REGS 10 10 # define NUM_MSI_ALLOC_SCRATCHPAD_REGS 2 ··· 36 36 37 37 #define GENERIC_MSI_DOMAIN_OPS 1 38 38 39 - #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */ 39 + #endif /* CONFIG_GENERIC_MSI_IRQ */ 40 40 41 41 #endif
+3 -1
include/clocksource/hyperv_timer.h
··· 15 15 16 16 #include <linux/clocksource.h> 17 17 #include <linux/math64.h> 18 - #include <asm/mshyperv.h> 18 + #include <asm/hyperv-tlfs.h> 19 19 20 20 #define HV_MAX_MAX_DELTA_TICKS 0xffffffff 21 21 #define HV_MIN_DELTA_TICKS 1 22 22 23 23 #ifdef CONFIG_HYPERV_TIMER 24 + 25 + #include <asm/hyperv_timer.h> 24 26 25 27 /* Routines called by the VMbus driver */ 26 28 extern int hv_stimer_alloc(bool have_percpu_irqs);
+3 -5
include/linux/device.h
··· 378 378 * @data: Pointer to MSI device data 379 379 */ 380 380 struct dev_msi_info { 381 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 382 - struct irq_domain *domain; 383 - #endif 384 381 #ifdef CONFIG_GENERIC_MSI_IRQ 382 + struct irq_domain *domain; 385 383 struct msi_device_data *data; 386 384 #endif 387 385 }; ··· 740 742 741 743 static inline struct irq_domain *dev_get_msi_domain(const struct device *dev) 742 744 { 743 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 745 + #ifdef CONFIG_GENERIC_MSI_IRQ 744 746 return dev->msi.domain; 745 747 #else 746 748 return NULL; ··· 749 751 750 752 static inline void dev_set_msi_domain(struct device *dev, struct irq_domain *d) 751 753 { 752 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 754 + #ifdef CONFIG_GENERIC_MSI_IRQ 753 755 dev->msi.domain = d; 754 756 #endif 755 757 }
+1 -1
include/linux/gpio/driver.h
··· 27 27 28 28 union gpio_irq_fwspec { 29 29 struct irq_fwspec fwspec; 30 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 30 + #ifdef CONFIG_GENERIC_MSI_IRQ 31 31 msi_alloc_info_t msiinfo; 32 32 #endif 33 33 };
+76 -67
include/linux/irqdomain.h
··· 31 31 #define _LINUX_IRQDOMAIN_H 32 32 33 33 #include <linux/types.h> 34 + #include <linux/irqdomain_defs.h> 34 35 #include <linux/irqhandler.h> 35 36 #include <linux/of.h> 36 37 #include <linux/mutex.h> ··· 46 45 struct cpumask; 47 46 struct seq_file; 48 47 struct irq_affinity_desc; 48 + struct msi_parent_ops; 49 49 50 50 #define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16 51 51 ··· 69 67 /* Conversion function from of_phandle_args fields to fwspec */ 70 68 void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, 71 69 unsigned int count, struct irq_fwspec *fwspec); 72 - 73 - /* 74 - * Should several domains have the same device node, but serve 75 - * different purposes (for example one domain is for PCI/MSI, and the 76 - * other for wired IRQs), they can be distinguished using a 77 - * bus-specific token. Most domains are expected to only carry 78 - * DOMAIN_BUS_ANY. 79 - */ 80 - enum irq_domain_bus_token { 81 - DOMAIN_BUS_ANY = 0, 82 - DOMAIN_BUS_WIRED, 83 - DOMAIN_BUS_GENERIC_MSI, 84 - DOMAIN_BUS_PCI_MSI, 85 - DOMAIN_BUS_PLATFORM_MSI, 86 - DOMAIN_BUS_NEXUS, 87 - DOMAIN_BUS_IPI, 88 - DOMAIN_BUS_FSL_MC_MSI, 89 - DOMAIN_BUS_TI_SCI_INTA_MSI, 90 - DOMAIN_BUS_WAKEUP, 91 - DOMAIN_BUS_VMD_MSI, 92 - }; 93 70 94 71 /** 95 72 * struct irq_domain_ops - Methods for irq_domain objects ··· 118 137 119 138 /** 120 139 * struct irq_domain - Hardware interrupt number translation object 121 - * @link: Element in global irq_domain list. 122 - * @name: Name of interrupt domain 123 - * @ops: pointer to irq_domain methods 124 - * @host_data: private data pointer for use by owner. Not touched by irq_domain 125 - * core code. 126 - * @flags: host per irq_domain flags 127 - * @mapcount: The number of mapped interrupts 140 + * @link: Element in global irq_domain list. 141 + * @name: Name of interrupt domain 142 + * @ops: Pointer to irq_domain methods 143 + * @host_data: Private data pointer for use by owner. Not touched by irq_domain 144 + * core code. 145 + * @flags: Per irq_domain flags 146 + * @mapcount: The number of mapped interrupts 128 147 * 129 - * Optional elements 130 - * @fwnode: Pointer to firmware node associated with the irq_domain. Pretty easy 131 - * to swap it for the of_node via the irq_domain_get_of_node accessor 132 - * @gc: Pointer to a list of generic chips. There is a helper function for 133 - * setting up one or more generic chips for interrupt controllers 134 - * drivers using the generic chip library which uses this pointer. 135 - * @dev: Pointer to a device that the domain represent, and that will be 136 - * used for power management purposes. 137 - * @parent: Pointer to parent irq_domain to support hierarchy irq_domains 148 + * Optional elements: 149 + * @fwnode: Pointer to firmware node associated with the irq_domain. Pretty easy 150 + * to swap it for the of_node via the irq_domain_get_of_node accessor 151 + * @gc: Pointer to a list of generic chips. There is a helper function for 152 + * setting up one or more generic chips for interrupt controllers 153 + * drivers using the generic chip library which uses this pointer. 154 + * @dev: Pointer to the device which instantiated the irqdomain 155 + * With per device irq domains this is not necessarily the same 156 + * as @pm_dev. 157 + * @pm_dev: Pointer to a device that can be utilized for power management 158 + * purposes related to the irq domain. 159 + * @parent: Pointer to parent irq_domain to support hierarchy irq_domains 160 + * @msi_parent_ops: Pointer to MSI parent domain methods for per device domain init 138 161 * 139 - * Revmap data, used internally by irq_domain 140 - * @revmap_size: Size of the linear map table @revmap[] 141 - * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map 142 - * @revmap_mutex: Lock for the revmap 143 - * @revmap: Linear table of irq_data pointers 162 + * Revmap data, used internally by the irq domain code: 163 + * @revmap_size: Size of the linear map table @revmap[] 164 + * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map 165 + * @revmap_mutex: Lock for the revmap 166 + * @revmap: Linear table of irq_data pointers 144 167 */ 145 168 struct irq_domain { 146 - struct list_head link; 147 - const char *name; 148 - const struct irq_domain_ops *ops; 149 - void *host_data; 150 - unsigned int flags; 151 - unsigned int mapcount; 169 + struct list_head link; 170 + const char *name; 171 + const struct irq_domain_ops *ops; 172 + void *host_data; 173 + unsigned int flags; 174 + unsigned int mapcount; 152 175 153 176 /* Optional data */ 154 - struct fwnode_handle *fwnode; 155 - enum irq_domain_bus_token bus_token; 156 - struct irq_domain_chip_generic *gc; 157 - struct device *dev; 177 + struct fwnode_handle *fwnode; 178 + enum irq_domain_bus_token bus_token; 179 + struct irq_domain_chip_generic *gc; 180 + struct device *dev; 181 + struct device *pm_dev; 158 182 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 159 - struct irq_domain *parent; 183 + struct irq_domain *parent; 184 + #endif 185 + #ifdef CONFIG_GENERIC_MSI_IRQ 186 + const struct msi_parent_ops *msi_parent_ops; 160 187 #endif 161 188 162 189 /* reverse map data. The linear map gets appended to the irq_domain */ 163 - irq_hw_number_t hwirq_max; 164 - unsigned int revmap_size; 165 - struct radix_tree_root revmap_tree; 166 - struct mutex revmap_mutex; 167 - struct irq_data __rcu *revmap[]; 190 + irq_hw_number_t hwirq_max; 191 + unsigned int revmap_size; 192 + struct radix_tree_root revmap_tree; 193 + struct mutex revmap_mutex; 194 + struct irq_data __rcu *revmap[]; 168 195 }; 169 196 170 197 /* Irq domain flags */ ··· 195 206 /* Irq domain implements MSI remapping */ 196 207 IRQ_DOMAIN_FLAG_MSI_REMAP = (1 << 5), 197 208 198 - /* 199 - * Quirk to handle MSI implementations which do not provide 200 - * masking. Currently known to affect x86, but partially 201 - * handled in core code. 202 - */ 203 - IRQ_DOMAIN_MSI_NOMASK_QUIRK = (1 << 6), 204 - 205 209 /* Irq domain doesn't translate anything */ 206 - IRQ_DOMAIN_FLAG_NO_MAP = (1 << 7), 210 + IRQ_DOMAIN_FLAG_NO_MAP = (1 << 6), 211 + 212 + /* Irq domain is a MSI parent domain */ 213 + IRQ_DOMAIN_FLAG_MSI_PARENT = (1 << 8), 214 + 215 + /* Irq domain is a MSI device domain */ 216 + IRQ_DOMAIN_FLAG_MSI_DEVICE = (1 << 9), 207 217 208 218 /* 209 219 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved ··· 221 233 struct device *dev) 222 234 { 223 235 if (d) 224 - d->dev = dev; 236 + d->pm_dev = dev; 225 237 } 226 238 227 239 #ifdef CONFIG_IRQ_DOMAIN ··· 566 578 567 579 extern bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain); 568 580 581 + static inline bool irq_domain_is_msi_parent(struct irq_domain *domain) 582 + { 583 + return domain->flags & IRQ_DOMAIN_FLAG_MSI_PARENT; 584 + } 585 + 586 + static inline bool irq_domain_is_msi_device(struct irq_domain *domain) 587 + { 588 + return domain->flags & IRQ_DOMAIN_FLAG_MSI_DEVICE; 589 + } 590 + 569 591 #else /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 570 592 static inline int irq_domain_alloc_irqs(struct irq_domain *domain, 571 593 unsigned int nr_irqs, int node, void *arg) ··· 621 623 { 622 624 return false; 623 625 } 626 + 627 + static inline bool irq_domain_is_msi_parent(struct irq_domain *domain) 628 + { 629 + return false; 630 + } 631 + 632 + static inline bool irq_domain_is_msi_device(struct irq_domain *domain) 633 + { 634 + return false; 635 + } 636 + 624 637 #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 625 638 626 639 #else /* CONFIG_IRQ_DOMAIN */
+31
include/linux/irqdomain_defs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _LINUX_IRQDOMAIN_DEFS_H 3 + #define _LINUX_IRQDOMAIN_DEFS_H 4 + 5 + /* 6 + * Should several domains have the same device node, but serve 7 + * different purposes (for example one domain is for PCI/MSI, and the 8 + * other for wired IRQs), they can be distinguished using a 9 + * bus-specific token. Most domains are expected to only carry 10 + * DOMAIN_BUS_ANY. 11 + */ 12 + enum irq_domain_bus_token { 13 + DOMAIN_BUS_ANY = 0, 14 + DOMAIN_BUS_WIRED, 15 + DOMAIN_BUS_GENERIC_MSI, 16 + DOMAIN_BUS_PCI_MSI, 17 + DOMAIN_BUS_PLATFORM_MSI, 18 + DOMAIN_BUS_NEXUS, 19 + DOMAIN_BUS_IPI, 20 + DOMAIN_BUS_FSL_MC_MSI, 21 + DOMAIN_BUS_TI_SCI_INTA_MSI, 22 + DOMAIN_BUS_WAKEUP, 23 + DOMAIN_BUS_VMD_MSI, 24 + DOMAIN_BUS_PCI_DEVICE_MSI, 25 + DOMAIN_BUS_PCI_DEVICE_MSIX, 26 + DOMAIN_BUS_DMAR, 27 + DOMAIN_BUS_AMDVI, 28 + DOMAIN_BUS_PCI_DEVICE_IMS, 29 + }; 30 + 31 + #endif /* _LINUX_IRQDOMAIN_DEFS_H */
+4 -4
include/linux/irqreturn.h
··· 3 3 #define _LINUX_IRQRETURN_H 4 4 5 5 /** 6 - * enum irqreturn 7 - * @IRQ_NONE interrupt was not from this device or was not handled 8 - * @IRQ_HANDLED interrupt was handled by this device 9 - * @IRQ_WAKE_THREAD handler requests to wake the handler thread 6 + * enum irqreturn - irqreturn type values 7 + * @IRQ_NONE: interrupt was not from this device or was not handled 8 + * @IRQ_HANDLED: interrupt was handled by this device 9 + * @IRQ_WAKE_THREAD: handler requests to wake the handler thread 10 10 */ 11 11 enum irqreturn { 12 12 IRQ_NONE = (0 << 0),
+273 -84
include/linux/msi.h
··· 13 13 * 14 14 * Regular device drivers have no business with any of these functions and 15 15 * especially storing MSI descriptor pointers in random code is considered 16 - * abuse. The only function which is relevant for drivers is msi_get_virq(). 16 + * abuse. 17 + * 18 + * Device driver relevant functions are available in <linux/msi_api.h> 17 19 */ 18 20 21 + #include <linux/irqdomain_defs.h> 19 22 #include <linux/cpumask.h> 23 + #include <linux/msi_api.h> 20 24 #include <linux/xarray.h> 21 25 #include <linux/mutex.h> 22 26 #include <linux/list.h> 27 + #include <linux/irq.h> 28 + #include <linux/bits.h> 29 + 23 30 #include <asm/msi.h> 24 31 25 32 /* Dummy shadow structures if an architecture does not define them */ ··· 75 68 76 69 extern int pci_msi_ignore_mask; 77 70 /* Helper functions */ 78 - struct irq_data; 79 71 struct msi_desc; 80 72 struct pci_dev; 81 73 struct platform_msi_priv_data; 82 74 struct device_attribute; 75 + struct irq_domain; 76 + struct irq_affinity_desc; 83 77 84 78 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 85 79 #ifdef CONFIG_GENERIC_MSI_IRQ 86 80 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); 87 81 #else 88 - static inline void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) 89 - { 90 - } 82 + static inline void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) { } 91 83 #endif 92 84 93 85 typedef void (*irq_write_msi_msg_t)(struct msi_desc *desc, ··· 126 120 }; 127 121 }; 128 122 123 + /** 124 + * union msi_domain_cookie - Opaque MSI domain specific data 125 + * @value: u64 value store 126 + * @ptr: Pointer to domain specific data 127 + * @iobase: Domain specific IOmem pointer 128 + * 129 + * The content of this data is implementation defined and used by the MSI 130 + * domain to store domain specific information which is requried for 131 + * interrupt chip callbacks. 132 + */ 133 + union msi_domain_cookie { 134 + u64 value; 135 + void *ptr; 136 + void __iomem *iobase; 137 + }; 138 + 139 + /** 140 + * struct msi_desc_data - Generic MSI descriptor data 141 + * @dcookie: Cookie for MSI domain specific data which is required 142 + * for irq_chip callbacks 143 + * @icookie: Cookie for the MSI interrupt instance provided by 144 + * the usage site to the allocation function 145 + * 146 + * The content of this data is implementation defined, e.g. PCI/IMS 147 + * implementations define the meaning of the data. The MSI core ignores 148 + * this data completely. 149 + */ 150 + struct msi_desc_data { 151 + union msi_domain_cookie dcookie; 152 + union msi_instance_cookie icookie; 153 + }; 154 + 129 155 #define MSI_MAX_INDEX ((unsigned int)USHRT_MAX) 130 156 131 157 /** ··· 175 137 * 176 138 * @msi_index: Index of the msi descriptor 177 139 * @pci: PCI specific msi descriptor data 140 + * @data: Generic MSI descriptor data 178 141 */ 179 142 struct msi_desc { 180 143 /* Shared device/bus type independent data */ ··· 195 156 void *write_msi_msg_data; 196 157 197 158 u16 msi_index; 198 - struct pci_msi_desc pci; 159 + union { 160 + struct pci_msi_desc pci; 161 + struct msi_desc_data data; 162 + }; 199 163 }; 200 164 201 165 /* ··· 213 171 MSI_DESC_ASSOCIATED, 214 172 }; 215 173 174 + 175 + /** 176 + * struct msi_dev_domain - The internals of MSI domain info per device 177 + * @store: Xarray for storing MSI descriptor pointers 178 + * @irqdomain: Pointer to a per device interrupt domain 179 + */ 180 + struct msi_dev_domain { 181 + struct xarray store; 182 + struct irq_domain *domain; 183 + }; 184 + 216 185 /** 217 186 * msi_device_data - MSI per device data 218 187 * @properties: MSI properties which are interesting to drivers 219 188 * @platform_data: Platform-MSI specific data 220 189 * @mutex: Mutex protecting the MSI descriptor store 221 - * @__store: Xarray for storing MSI descriptor pointers 190 + * @__domains: Internal data for per device MSI domains 222 191 * @__iter_idx: Index to search the next entry for iterators 223 192 */ 224 193 struct msi_device_data { 225 194 unsigned long properties; 226 195 struct platform_msi_priv_data *platform_data; 227 196 struct mutex mutex; 228 - struct xarray __store; 197 + struct msi_dev_domain __domains[MSI_MAX_DEVICE_IRQDOMAINS]; 229 198 unsigned long __iter_idx; 230 199 }; 231 200 232 201 int msi_setup_device_data(struct device *dev); 233 202 234 - unsigned int msi_get_virq(struct device *dev, unsigned int index); 235 203 void msi_lock_descs(struct device *dev); 236 204 void msi_unlock_descs(struct device *dev); 237 205 238 - struct msi_desc *msi_first_desc(struct device *dev, enum msi_desc_filter filter); 239 - struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter); 206 + struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, 207 + enum msi_desc_filter filter); 240 208 241 209 /** 242 - * msi_for_each_desc - Iterate the MSI descriptors 210 + * msi_first_desc - Get the first MSI descriptor of the default irqdomain 211 + * @dev: Device to operate on 212 + * @filter: Descriptor state filter 213 + * 214 + * Must be called with the MSI descriptor mutex held, i.e. msi_lock_descs() 215 + * must be invoked before the call. 216 + * 217 + * Return: Pointer to the first MSI descriptor matching the search 218 + * criteria, NULL if none found. 219 + */ 220 + static inline struct msi_desc *msi_first_desc(struct device *dev, 221 + enum msi_desc_filter filter) 222 + { 223 + return msi_domain_first_desc(dev, MSI_DEFAULT_DOMAIN, filter); 224 + } 225 + 226 + struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, 227 + enum msi_desc_filter filter); 228 + 229 + /** 230 + * msi_domain_for_each_desc - Iterate the MSI descriptors in a specific domain 231 + * 232 + * @desc: struct msi_desc pointer used as iterator 233 + * @dev: struct device pointer - device to iterate 234 + * @domid: The id of the interrupt domain which should be walked. 235 + * @filter: Filter for descriptor selection 236 + * 237 + * Notes: 238 + * - The loop must be protected with a msi_lock_descs()/msi_unlock_descs() 239 + * pair. 240 + * - It is safe to remove a retrieved MSI descriptor in the loop. 241 + */ 242 + #define msi_domain_for_each_desc(desc, dev, domid, filter) \ 243 + for ((desc) = msi_domain_first_desc((dev), (domid), (filter)); (desc); \ 244 + (desc) = msi_next_desc((dev), (domid), (filter))) 245 + 246 + /** 247 + * msi_for_each_desc - Iterate the MSI descriptors in the default irqdomain 243 248 * 244 249 * @desc: struct msi_desc pointer used as iterator 245 250 * @dev: struct device pointer - device to iterate ··· 297 208 * pair. 298 209 * - It is safe to remove a retrieved MSI descriptor in the loop. 299 210 */ 300 - #define msi_for_each_desc(desc, dev, filter) \ 301 - for ((desc) = msi_first_desc((dev), (filter)); (desc); \ 302 - (desc) = msi_next_desc((dev), (filter))) 211 + #define msi_for_each_desc(desc, dev, filter) \ 212 + msi_domain_for_each_desc((desc), (dev), MSI_DEFAULT_DOMAIN, (filter)) 303 213 304 214 #define msi_desc_to_dev(desc) ((desc)->dev) 305 215 ··· 325 237 } 326 238 #endif 327 239 328 - #ifdef CONFIG_PCI_MSI 329 - struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc); 330 - void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg); 331 - #else /* CONFIG_PCI_MSI */ 332 - static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) 240 + int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, 241 + struct msi_desc *init_desc); 242 + /** 243 + * msi_insert_msi_desc - Allocate and initialize a MSI descriptor in the 244 + * default irqdomain and insert it at @init_desc->msi_index 245 + * @dev: Pointer to the device for which the descriptor is allocated 246 + * @init_desc: Pointer to an MSI descriptor to initialize the new descriptor 247 + * 248 + * Return: 0 on success or an appropriate failure code. 249 + */ 250 + static inline int msi_insert_msi_desc(struct device *dev, struct msi_desc *init_desc) 333 251 { 252 + return msi_domain_insert_msi_desc(dev, MSI_DEFAULT_DOMAIN, init_desc); 334 253 } 335 - #endif /* CONFIG_PCI_MSI */ 336 254 337 - int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc); 338 - void msi_free_msi_descs_range(struct device *dev, enum msi_desc_filter filter, 339 - unsigned int first_index, unsigned int last_index); 255 + void msi_domain_free_msi_descs_range(struct device *dev, unsigned int domid, 256 + unsigned int first, unsigned int last); 340 257 341 258 /** 342 - * msi_free_msi_descs - Free MSI descriptors of a device 259 + * msi_free_msi_descs_range - Free a range of MSI descriptors of a device 260 + * in the default irqdomain 261 + * 262 + * @dev: Device for which to free the descriptors 263 + * @first: Index to start freeing from (inclusive) 264 + * @last: Last index to be freed (inclusive) 265 + */ 266 + static inline void msi_free_msi_descs_range(struct device *dev, unsigned int first, 267 + unsigned int last) 268 + { 269 + msi_domain_free_msi_descs_range(dev, MSI_DEFAULT_DOMAIN, first, last); 270 + } 271 + 272 + /** 273 + * msi_free_msi_descs - Free all MSI descriptors of a device in the default irqdomain 343 274 * @dev: Device to free the descriptors 344 275 */ 345 276 static inline void msi_free_msi_descs(struct device *dev) 346 277 { 347 - msi_free_msi_descs_range(dev, MSI_DESC_ALL, 0, MSI_MAX_INDEX); 278 + msi_free_msi_descs_range(dev, 0, MSI_MAX_INDEX); 348 279 } 349 - 350 - void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 351 - void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 352 - 353 - void pci_msi_mask_irq(struct irq_data *data); 354 - void pci_msi_unmask_irq(struct irq_data *data); 355 280 356 281 /* 357 282 * The arch hooks to setup up msi irqs. Default functions are implemented ··· 394 293 */ 395 294 bool arch_restore_msi_irqs(struct pci_dev *dev); 396 295 397 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 296 + #ifdef CONFIG_GENERIC_MSI_IRQ 398 297 399 298 #include <linux/irqhandler.h> 400 299 ··· 410 309 * @get_hwirq: Retrieve the resulting hw irq number 411 310 * @msi_init: Domain specific init function for MSI interrupts 412 311 * @msi_free: Domain specific function to free a MSI interrupts 413 - * @msi_check: Callback for verification of the domain/info/dev data 414 312 * @msi_prepare: Prepare the allocation of the interrupts in the domain 313 + * @prepare_desc: Optional function to prepare the allocated MSI descriptor 314 + * in the domain 415 315 * @set_desc: Set the msi descriptor for an interrupt 416 316 * @domain_alloc_irqs: Optional function to override the default allocation 417 317 * function. 418 318 * @domain_free_irqs: Optional function to override the default free 419 319 * function. 320 + * @msi_post_free: Optional function which is invoked after freeing 321 + * all interrupts. 420 322 * 421 323 * @get_hwirq, @msi_init and @msi_free are callbacks used by the underlying 422 324 * irqdomain. 423 325 * 424 - * @msi_check, @msi_prepare and @set_desc are callbacks used by 425 - * msi_domain_alloc/free_irqs(). 326 + * @msi_check, @msi_prepare, @prepare_desc and @set_desc are callbacks used by the 327 + * msi_domain_alloc/free_irqs*() variants. 426 328 * 427 329 * @domain_alloc_irqs, @domain_free_irqs can be used to override the 428 330 * default allocation/free functions (__msi_domain_alloc/free_irqs). This ··· 433 329 * be wrapped into the regular irq domains concepts by mere mortals. This 434 330 * allows to universally use msi_domain_alloc/free_irqs without having to 435 331 * special case XEN all over the place. 436 - * 437 - * Contrary to other operations @domain_alloc_irqs and @domain_free_irqs 438 - * are set to the default implementation if NULL and even when 439 - * MSI_FLAG_USE_DEF_DOM_OPS is not set to avoid breaking existing users and 440 - * because these callbacks are obviously mandatory. 441 - * 442 - * This is NOT meant to be abused, but it can be useful to build wrappers 443 - * for specialized MSI irq domains which need extra work before and after 444 - * calling __msi_domain_alloc_irqs()/__msi_domain_free_irqs(). 445 332 */ 446 333 struct msi_domain_ops { 447 334 irq_hw_number_t (*get_hwirq)(struct msi_domain_info *info, ··· 444 349 void (*msi_free)(struct irq_domain *domain, 445 350 struct msi_domain_info *info, 446 351 unsigned int virq); 447 - int (*msi_check)(struct irq_domain *domain, 448 - struct msi_domain_info *info, 449 - struct device *dev); 450 352 int (*msi_prepare)(struct irq_domain *domain, 451 353 struct device *dev, int nvec, 452 354 msi_alloc_info_t *arg); 355 + void (*prepare_desc)(struct irq_domain *domain, msi_alloc_info_t *arg, 356 + struct msi_desc *desc); 453 357 void (*set_desc)(msi_alloc_info_t *arg, 454 358 struct msi_desc *desc); 455 359 int (*domain_alloc_irqs)(struct irq_domain *domain, 456 360 struct device *dev, int nvec); 457 361 void (*domain_free_irqs)(struct irq_domain *domain, 458 362 struct device *dev); 363 + void (*msi_post_free)(struct irq_domain *domain, 364 + struct device *dev); 459 365 }; 460 366 461 367 /** 462 368 * struct msi_domain_info - MSI interrupt domain data 463 369 * @flags: Flags to decribe features and capabilities 370 + * @bus_token: The domain bus token 371 + * @hwsize: The hardware table size or the software index limit. 372 + * If 0 then the size is considered unlimited and 373 + * gets initialized to the maximum software index limit 374 + * by the domain creation code. 464 375 * @ops: The callback data structure 465 376 * @chip: Optional: associated interrupt chip 466 377 * @chip_data: Optional: associated interrupt chip data ··· 476 375 * @data: Optional: domain specific data 477 376 */ 478 377 struct msi_domain_info { 479 - u32 flags; 480 - struct msi_domain_ops *ops; 481 - struct irq_chip *chip; 482 - void *chip_data; 483 - irq_flow_handler_t handler; 484 - void *handler_data; 485 - const char *handler_name; 486 - void *data; 378 + u32 flags; 379 + enum irq_domain_bus_token bus_token; 380 + unsigned int hwsize; 381 + struct msi_domain_ops *ops; 382 + struct irq_chip *chip; 383 + void *chip_data; 384 + irq_flow_handler_t handler; 385 + void *handler_data; 386 + const char *handler_name; 387 + void *data; 487 388 }; 488 389 489 - /* Flags for msi_domain_info */ 390 + /** 391 + * struct msi_domain_template - Template for MSI device domains 392 + * @name: Storage for the resulting name. Filled in by the core. 393 + * @chip: Interrupt chip for this domain 394 + * @ops: MSI domain ops 395 + * @info: MSI domain info data 396 + */ 397 + struct msi_domain_template { 398 + char name[48]; 399 + struct irq_chip chip; 400 + struct msi_domain_ops ops; 401 + struct msi_domain_info info; 402 + }; 403 + 404 + /* 405 + * Flags for msi_domain_info 406 + * 407 + * Bit 0-15: Generic MSI functionality which is not subject to restriction 408 + * by parent domains 409 + * 410 + * Bit 16-31: Functionality which depends on the underlying parent domain and 411 + * can be masked out by msi_parent_ops::init_dev_msi_info() when 412 + * a device MSI domain is initialized. 413 + */ 490 414 enum { 491 415 /* 492 416 * Init non implemented ops callbacks with default MSI domain ··· 523 397 * callbacks. 524 398 */ 525 399 MSI_FLAG_USE_DEF_CHIP_OPS = (1 << 1), 526 - /* Support multiple PCI MSI interrupts */ 527 - MSI_FLAG_MULTI_PCI_MSI = (1 << 2), 528 - /* Support PCI MSIX interrupts */ 529 - MSI_FLAG_PCI_MSIX = (1 << 3), 530 400 /* Needs early activate, required for PCI */ 531 - MSI_FLAG_ACTIVATE_EARLY = (1 << 4), 401 + MSI_FLAG_ACTIVATE_EARLY = (1 << 2), 532 402 /* 533 403 * Must reactivate when irq is started even when 534 404 * MSI_FLAG_ACTIVATE_EARLY has been set. 535 405 */ 536 - MSI_FLAG_MUST_REACTIVATE = (1 << 5), 537 - /* Is level-triggered capable, using two messages */ 538 - MSI_FLAG_LEVEL_CAPABLE = (1 << 6), 406 + MSI_FLAG_MUST_REACTIVATE = (1 << 3), 539 407 /* Populate sysfs on alloc() and destroy it on free() */ 540 - MSI_FLAG_DEV_SYSFS = (1 << 7), 541 - /* MSI-X entries must be contiguous */ 542 - MSI_FLAG_MSIX_CONTIGUOUS = (1 << 8), 408 + MSI_FLAG_DEV_SYSFS = (1 << 4), 543 409 /* Allocate simple MSI descriptors */ 544 - MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 9), 410 + MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 5), 545 411 /* Free MSI descriptors */ 546 - MSI_FLAG_FREE_MSI_DESCS = (1 << 10), 412 + MSI_FLAG_FREE_MSI_DESCS = (1 << 6), 413 + /* 414 + * Quirk to handle MSI implementations which do not provide 415 + * masking. Currently known to affect x86, but has to be partially 416 + * handled in the core MSI code. 417 + */ 418 + MSI_FLAG_NOMASK_QUIRK = (1 << 7), 419 + 420 + /* Mask for the generic functionality */ 421 + MSI_GENERIC_FLAGS_MASK = GENMASK(15, 0), 422 + 423 + /* Mask for the domain specific functionality */ 424 + MSI_DOMAIN_FLAGS_MASK = GENMASK(31, 16), 425 + 426 + /* Support multiple PCI MSI interrupts */ 427 + MSI_FLAG_MULTI_PCI_MSI = (1 << 16), 428 + /* Support PCI MSIX interrupts */ 429 + MSI_FLAG_PCI_MSIX = (1 << 17), 430 + /* Is level-triggered capable, using two messages */ 431 + MSI_FLAG_LEVEL_CAPABLE = (1 << 18), 432 + /* MSI-X entries must be contiguous */ 433 + MSI_FLAG_MSIX_CONTIGUOUS = (1 << 19), 434 + /* PCI/MSI-X vectors can be dynamically allocated/freed post MSI-X enable */ 435 + MSI_FLAG_PCI_MSIX_ALLOC_DYN = (1 << 20), 436 + /* Support for PCI/IMS */ 437 + MSI_FLAG_PCI_IMS = (1 << 21), 547 438 }; 439 + 440 + /** 441 + * struct msi_parent_ops - MSI parent domain callbacks and configuration info 442 + * 443 + * @supported_flags: Required: The supported MSI flags of the parent domain 444 + * @prefix: Optional: Prefix for the domain and chip name 445 + * @init_dev_msi_info: Required: Callback for MSI parent domains to setup parent 446 + * domain specific domain flags, domain ops and interrupt chip 447 + * callbacks when a per device domain is created. 448 + */ 449 + struct msi_parent_ops { 450 + u32 supported_flags; 451 + const char *prefix; 452 + bool (*init_dev_msi_info)(struct device *dev, struct irq_domain *domain, 453 + struct irq_domain *msi_parent_domain, 454 + struct msi_domain_info *msi_child_info); 455 + }; 456 + 457 + bool msi_parent_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 458 + struct irq_domain *msi_parent_domain, 459 + struct msi_domain_info *msi_child_info); 548 460 549 461 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, 550 462 bool force); ··· 590 426 struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, 591 427 struct msi_domain_info *info, 592 428 struct irq_domain *parent); 593 - int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, 594 - int nvec); 595 - int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev, 596 - int nvec); 597 - int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, 598 - int nvec); 599 - void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); 600 - void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev); 601 - void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); 429 + 430 + bool msi_create_device_irq_domain(struct device *dev, unsigned int domid, 431 + const struct msi_domain_template *template, 432 + unsigned int hwsize, void *domain_data, 433 + void *chip_data); 434 + void msi_remove_device_irq_domain(struct device *dev, unsigned int domid); 435 + 436 + bool msi_match_device_irq_domain(struct device *dev, unsigned int domid, 437 + enum irq_domain_bus_token bus_token); 438 + 439 + int msi_domain_alloc_irqs_range_locked(struct device *dev, unsigned int domid, 440 + unsigned int first, unsigned int last); 441 + int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, 442 + unsigned int first, unsigned int last); 443 + int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int nirqs); 444 + 445 + struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index, 446 + const struct irq_affinity_desc *affdesc, 447 + union msi_instance_cookie *cookie); 448 + 449 + void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, 450 + unsigned int first, unsigned int last); 451 + void msi_domain_free_irqs_range(struct device *dev, unsigned int domid, 452 + unsigned int first, unsigned int last); 453 + void msi_domain_free_irqs_all_locked(struct device *dev, unsigned int domid); 454 + void msi_domain_free_irqs_all(struct device *dev, unsigned int domid); 455 + 602 456 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain); 603 457 604 458 struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode, ··· 649 467 void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq, 650 468 unsigned int nvec); 651 469 void *platform_msi_get_host_data(struct irq_domain *domain); 652 - #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */ 470 + #endif /* CONFIG_GENERIC_MSI_IRQ */ 653 471 654 - #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 472 + /* PCI specific interfaces */ 473 + #ifdef CONFIG_PCI_MSI 474 + struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc); 475 + void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg); 476 + void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 477 + void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 478 + void pci_msi_mask_irq(struct irq_data *data); 479 + void pci_msi_unmask_irq(struct irq_data *data); 655 480 struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, 656 481 struct msi_domain_info *info, 657 482 struct irq_domain *parent); 658 483 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev); 659 484 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev); 660 - bool pci_dev_has_special_msi_domain(struct pci_dev *pdev); 661 - #else 485 + #else /* CONFIG_PCI_MSI */ 662 486 static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) 663 487 { 664 488 return NULL; 665 489 } 666 - #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */ 490 + static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) { } 491 + #endif /* !CONFIG_PCI_MSI */ 667 492 668 493 #endif /* LINUX_MSI_H */
+73
include/linux/msi_api.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef LINUX_MSI_API_H 3 + #define LINUX_MSI_API_H 4 + 5 + /* 6 + * APIs which are relevant for device driver code for allocating and 7 + * freeing MSI interrupts and querying the associations between 8 + * hardware/software MSI indices and the Linux interrupt number. 9 + */ 10 + 11 + struct device; 12 + 13 + /* 14 + * Per device interrupt domain related constants. 15 + */ 16 + enum msi_domain_ids { 17 + MSI_DEFAULT_DOMAIN, 18 + MSI_SECONDARY_DOMAIN, 19 + MSI_MAX_DEVICE_IRQDOMAINS, 20 + }; 21 + 22 + /** 23 + * union msi_instance_cookie - MSI instance cookie 24 + * @value: u64 value store 25 + * @ptr: Pointer to usage site specific data 26 + * 27 + * This cookie is handed to the IMS allocation function and stored in the 28 + * MSI descriptor for the interrupt chip callbacks. 29 + * 30 + * The content of this cookie is MSI domain implementation defined. For 31 + * PCI/IMS implementations this could be a PASID or a pointer to queue 32 + * memory. 33 + */ 34 + union msi_instance_cookie { 35 + u64 value; 36 + void *ptr; 37 + }; 38 + 39 + /** 40 + * msi_map - Mapping between MSI index and Linux interrupt number 41 + * @index: The MSI index, e.g. slot in the MSI-X table or 42 + * a software managed index if >= 0. If negative 43 + * the allocation function failed and it contains 44 + * the error code. 45 + * @virq: The associated Linux interrupt number 46 + */ 47 + struct msi_map { 48 + int index; 49 + int virq; 50 + }; 51 + 52 + /* 53 + * Constant to be used for dynamic allocations when the allocation is any 54 + * free MSI index, which is either an entry in a hardware table or a 55 + * software managed index. 56 + */ 57 + #define MSI_ANY_INDEX UINT_MAX 58 + 59 + unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index); 60 + 61 + /** 62 + * msi_get_virq - Lookup the Linux interrupt number for a MSI index on the default interrupt domain 63 + * @dev: Device for which the lookup happens 64 + * @index: The MSI index to lookup 65 + * 66 + * Return: The Linux interrupt number on success (> 0), 0 if not found 67 + */ 68 + static inline unsigned int msi_get_virq(struct device *dev, unsigned int index) 69 + { 70 + return msi_domain_get_virq(dev, MSI_DEFAULT_DOMAIN, index); 71 + } 72 + 73 + #endif
+25 -4
include/linux/pci.h
··· 38 38 #include <linux/interrupt.h> 39 39 #include <linux/io.h> 40 40 #include <linux/resource_ext.h> 41 + #include <linux/msi_api.h> 41 42 #include <uapi/linux/pci.h> 42 43 43 44 #include <linux/pci_ids.h> ··· 1554 1553 return rc; 1555 1554 return 0; 1556 1555 } 1556 + int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 1557 + unsigned int max_vecs, unsigned int flags); 1557 1558 int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, 1558 1559 unsigned int max_vecs, unsigned int flags, 1559 1560 struct irq_affinity *affd); 1561 + 1562 + bool pci_msix_can_alloc_dyn(struct pci_dev *dev); 1563 + struct msi_map pci_msix_alloc_irq_at(struct pci_dev *dev, unsigned int index, 1564 + const struct irq_affinity_desc *affdesc); 1565 + void pci_msix_free_irq(struct pci_dev *pdev, struct msi_map map); 1560 1566 1561 1567 void pci_free_irq_vectors(struct pci_dev *dev); 1562 1568 int pci_irq_vector(struct pci_dev *dev, unsigned int nr); ··· 1593 1585 if ((flags & PCI_IRQ_LEGACY) && min_vecs == 1 && dev->irq) 1594 1586 return 1; 1595 1587 return -ENOSPC; 1588 + } 1589 + static inline int 1590 + pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 1591 + unsigned int max_vecs, unsigned int flags) 1592 + { 1593 + return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, 1594 + flags, NULL); 1596 1595 } 1597 1596 1598 1597 static inline void pci_free_irq_vectors(struct pci_dev *dev) ··· 1913 1898 { 1914 1899 return -ENOSPC; 1915 1900 } 1916 - #endif /* CONFIG_PCI */ 1917 - 1918 1901 static inline int 1919 1902 pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 1920 1903 unsigned int max_vecs, unsigned int flags) 1921 1904 { 1922 - return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags, 1923 - NULL); 1905 + return -ENOSPC; 1924 1906 } 1907 + #endif /* CONFIG_PCI */ 1925 1908 1926 1909 /* Include architecture-dependent settings and functions */ 1927 1910 ··· 2486 2473 #if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH) 2487 2474 void pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type); 2488 2475 #endif 2476 + 2477 + struct msi_domain_template; 2478 + 2479 + bool pci_create_ims_domain(struct pci_dev *pdev, const struct msi_domain_template *template, 2480 + unsigned int hwsize, void *data); 2481 + struct msi_map pci_ims_alloc_irq(struct pci_dev *pdev, union msi_instance_cookie *icookie, 2482 + const struct irq_affinity_desc *affdesc); 2483 + void pci_ims_free_irq(struct pci_dev *pdev, struct msi_map map); 2489 2484 2490 2485 #include <linux/dma-mapping.h> 2491 2486
+1 -6
kernel/irq/Kconfig
··· 86 86 depends on SMP 87 87 select IRQ_DOMAIN_HIERARCHY 88 88 89 - # Generic MSI interrupt support 89 + # Generic MSI hierarchical interrupt domain support 90 90 config GENERIC_MSI_IRQ 91 91 bool 92 - 93 - # Generic MSI hierarchical interrupt domain support 94 - config GENERIC_MSI_IRQ_DOMAIN 95 - bool 96 92 select IRQ_DOMAIN_HIERARCHY 97 - select GENERIC_MSI_IRQ 98 93 99 94 config IRQ_MSI_IOMMU 100 95 bool
+4 -4
kernel/irq/chip.c
··· 1561 1561 return 0; 1562 1562 } 1563 1563 1564 - static struct device *irq_get_parent_device(struct irq_data *data) 1564 + static struct device *irq_get_pm_device(struct irq_data *data) 1565 1565 { 1566 1566 if (data->domain) 1567 - return data->domain->dev; 1567 + return data->domain->pm_dev; 1568 1568 1569 1569 return NULL; 1570 1570 } ··· 1578 1578 */ 1579 1579 int irq_chip_pm_get(struct irq_data *data) 1580 1580 { 1581 - struct device *dev = irq_get_parent_device(data); 1581 + struct device *dev = irq_get_pm_device(data); 1582 1582 int retval = 0; 1583 1583 1584 1584 if (IS_ENABLED(CONFIG_PM) && dev) ··· 1597 1597 */ 1598 1598 int irq_chip_pm_put(struct irq_data *data) 1599 1599 { 1600 - struct device *dev = irq_get_parent_device(data); 1600 + struct device *dev = irq_get_pm_device(data); 1601 1601 int retval = 0; 1602 1602 1603 1603 if (IS_ENABLED(CONFIG_PM) && dev)
+2
kernel/irq/internals.h
··· 52 52 * IRQS_PENDING - irq is pending and replayed later 53 53 * IRQS_SUSPENDED - irq is suspended 54 54 * IRQS_NMI - irq line is used to deliver NMIs 55 + * IRQS_SYSFS - descriptor has been added to sysfs 55 56 */ 56 57 enum { 57 58 IRQS_AUTODETECT = 0x00000001, ··· 65 64 IRQS_SUSPENDED = 0x00000800, 66 65 IRQS_TIMINGS = 0x00001000, 67 66 IRQS_NMI = 0x00002000, 67 + IRQS_SYSFS = 0x00004000, 68 68 }; 69 69 70 70 #include "debug.h"
+9 -6
kernel/irq/irqdesc.c
··· 288 288 if (irq_kobj_base) { 289 289 /* 290 290 * Continue even in case of failure as this is nothing 291 - * crucial. 291 + * crucial and failures in the late irq_sysfs_init() 292 + * cannot be rolled back. 292 293 */ 293 294 if (kobject_add(&desc->kobj, irq_kobj_base, "%d", irq)) 294 295 pr_warn("Failed to add kobject for irq %d\n", irq); 296 + else 297 + desc->istate |= IRQS_SYSFS; 295 298 } 296 299 } 297 300 298 301 static void irq_sysfs_del(struct irq_desc *desc) 299 302 { 300 303 /* 301 - * If irq_sysfs_init() has not yet been invoked (early boot), then 302 - * irq_kobj_base is NULL and the descriptor was never added. 303 - * kobject_del() complains about a object with no parent, so make 304 - * it conditional. 304 + * Only invoke kobject_del() when kobject_add() was successfully 305 + * invoked for the descriptor. This covers both early boot, where 306 + * sysfs is not initialized yet, and the case of a failed 307 + * kobject_add() invocation. 305 308 */ 306 - if (irq_kobj_base) 309 + if (desc->istate & IRQS_SYSFS) 307 310 kobject_del(&desc->kobj); 308 311 } 309 312
+2 -2
kernel/irq/manage.c
··· 321 321 } 322 322 323 323 static bool irq_set_affinity_deactivated(struct irq_data *data, 324 - const struct cpumask *mask, bool force) 324 + const struct cpumask *mask) 325 325 { 326 326 struct irq_desc *desc = irq_data_to_desc(data); 327 327 ··· 354 354 if (!chip || !chip->irq_set_affinity) 355 355 return -EINVAL; 356 356 357 - if (irq_set_affinity_deactivated(data, mask, force)) 357 + if (irq_set_affinity_deactivated(data, mask)) 358 358 return 0; 359 359 360 360 if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
+745 -173
kernel/irq/msi.c
··· 19 19 20 20 #include "internals.h" 21 21 22 + /** 23 + * struct msi_ctrl - MSI internal management control structure 24 + * @domid: ID of the domain on which management operations should be done 25 + * @first: First (hardware) slot index to operate on 26 + * @last: Last (hardware) slot index to operate on 27 + * @nirqs: The number of Linux interrupts to allocate. Can be larger 28 + * than the range due to PCI/multi-MSI. 29 + */ 30 + struct msi_ctrl { 31 + unsigned int domid; 32 + unsigned int first; 33 + unsigned int last; 34 + unsigned int nirqs; 35 + }; 36 + 37 + /* Invalid Xarray index which is outside of any searchable range */ 38 + #define MSI_XA_MAX_INDEX (ULONG_MAX - 1) 39 + /* The maximum domain size */ 40 + #define MSI_XA_DOMAIN_SIZE (MSI_MAX_INDEX + 1) 41 + 42 + static void msi_domain_free_locked(struct device *dev, struct msi_ctrl *ctrl); 43 + static unsigned int msi_domain_get_hwsize(struct device *dev, unsigned int domid); 22 44 static inline int msi_sysfs_create_group(struct device *dev); 45 + 23 46 24 47 /** 25 48 * msi_alloc_desc - Allocate an initialized msi_desc ··· 56 33 * Return: pointer to allocated &msi_desc on success or %NULL on failure 57 34 */ 58 35 static struct msi_desc *msi_alloc_desc(struct device *dev, int nvec, 59 - const struct irq_affinity_desc *affinity) 36 + const struct irq_affinity_desc *affinity) 60 37 { 61 38 struct msi_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL); 62 39 ··· 81 58 kfree(desc); 82 59 } 83 60 84 - static int msi_insert_desc(struct msi_device_data *md, struct msi_desc *desc, unsigned int index) 61 + static int msi_insert_desc(struct device *dev, struct msi_desc *desc, 62 + unsigned int domid, unsigned int index) 85 63 { 64 + struct msi_device_data *md = dev->msi.data; 65 + struct xarray *xa = &md->__domains[domid].store; 66 + unsigned int hwsize; 86 67 int ret; 87 68 88 - desc->msi_index = index; 89 - ret = xa_insert(&md->__store, index, desc, GFP_KERNEL); 90 - if (ret) 91 - msi_free_desc(desc); 69 + hwsize = msi_domain_get_hwsize(dev, domid); 70 + 71 + if (index == MSI_ANY_INDEX) { 72 + struct xa_limit limit = { .min = 0, .max = hwsize - 1 }; 73 + unsigned int index; 74 + 75 + /* Let the xarray allocate a free index within the limit */ 76 + ret = xa_alloc(xa, &index, desc, limit, GFP_KERNEL); 77 + if (ret) 78 + goto fail; 79 + 80 + desc->msi_index = index; 81 + return 0; 82 + } else { 83 + if (index >= hwsize) { 84 + ret = -ERANGE; 85 + goto fail; 86 + } 87 + 88 + desc->msi_index = index; 89 + ret = xa_insert(xa, index, desc, GFP_KERNEL); 90 + if (ret) 91 + goto fail; 92 + return 0; 93 + } 94 + fail: 95 + msi_free_desc(desc); 92 96 return ret; 93 97 } 94 98 95 99 /** 96 - * msi_add_msi_desc - Allocate and initialize a MSI descriptor 100 + * msi_domain_insert_msi_desc - Allocate and initialize a MSI descriptor and 101 + * insert it at @init_desc->msi_index 102 + * 97 103 * @dev: Pointer to the device for which the descriptor is allocated 104 + * @domid: The id of the interrupt domain to which the desriptor is added 98 105 * @init_desc: Pointer to an MSI descriptor to initialize the new descriptor 99 106 * 100 107 * Return: 0 on success or an appropriate failure code. 101 108 */ 102 - int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc) 109 + int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, 110 + struct msi_desc *init_desc) 103 111 { 104 112 struct msi_desc *desc; 105 113 ··· 142 88 143 89 /* Copy type specific data to the new descriptor. */ 144 90 desc->pci = init_desc->pci; 145 - return msi_insert_desc(dev->msi.data, desc, init_desc->msi_index); 146 - } 147 91 148 - /** 149 - * msi_add_simple_msi_descs - Allocate and initialize MSI descriptors 150 - * @dev: Pointer to the device for which the descriptors are allocated 151 - * @index: Index for the first MSI descriptor 152 - * @ndesc: Number of descriptors to allocate 153 - * 154 - * Return: 0 on success or an appropriate failure code. 155 - */ 156 - static int msi_add_simple_msi_descs(struct device *dev, unsigned int index, unsigned int ndesc) 157 - { 158 - unsigned int idx, last = index + ndesc - 1; 159 - struct msi_desc *desc; 160 - int ret; 161 - 162 - lockdep_assert_held(&dev->msi.data->mutex); 163 - 164 - for (idx = index; idx <= last; idx++) { 165 - desc = msi_alloc_desc(dev, 1, NULL); 166 - if (!desc) 167 - goto fail_mem; 168 - ret = msi_insert_desc(dev->msi.data, desc, idx); 169 - if (ret) 170 - goto fail; 171 - } 172 - return 0; 173 - 174 - fail_mem: 175 - ret = -ENOMEM; 176 - fail: 177 - msi_free_msi_descs_range(dev, MSI_DESC_NOTASSOCIATED, index, last); 178 - return ret; 92 + return msi_insert_desc(dev, desc, domid, init_desc->msi_index); 179 93 } 180 94 181 95 static bool msi_desc_match(struct msi_desc *desc, enum msi_desc_filter filter) ··· 160 138 return false; 161 139 } 162 140 163 - /** 164 - * msi_free_msi_descs_range - Free MSI descriptors of a device 165 - * @dev: Device to free the descriptors 166 - * @filter: Descriptor state filter 167 - * @first_index: Index to start freeing from 168 - * @last_index: Last index to be freed 169 - */ 170 - void msi_free_msi_descs_range(struct device *dev, enum msi_desc_filter filter, 171 - unsigned int first_index, unsigned int last_index) 141 + static bool msi_ctrl_valid(struct device *dev, struct msi_ctrl *ctrl) 172 142 { 173 - struct xarray *xa = &dev->msi.data->__store; 143 + unsigned int hwsize; 144 + 145 + if (WARN_ON_ONCE(ctrl->domid >= MSI_MAX_DEVICE_IRQDOMAINS || 146 + !dev->msi.data->__domains[ctrl->domid].domain)) 147 + return false; 148 + 149 + hwsize = msi_domain_get_hwsize(dev, ctrl->domid); 150 + if (WARN_ON_ONCE(ctrl->first > ctrl->last || 151 + ctrl->first >= hwsize || 152 + ctrl->last >= hwsize)) 153 + return false; 154 + return true; 155 + } 156 + 157 + static void msi_domain_free_descs(struct device *dev, struct msi_ctrl *ctrl) 158 + { 174 159 struct msi_desc *desc; 160 + struct xarray *xa; 175 161 unsigned long idx; 176 162 177 163 lockdep_assert_held(&dev->msi.data->mutex); 178 164 179 - xa_for_each_range(xa, idx, desc, first_index, last_index) { 180 - if (msi_desc_match(desc, filter)) { 181 - xa_erase(xa, idx); 182 - msi_free_desc(desc); 183 - } 165 + if (!msi_ctrl_valid(dev, ctrl)) 166 + return; 167 + 168 + xa = &dev->msi.data->__domains[ctrl->domid].store; 169 + xa_for_each_range(xa, idx, desc, ctrl->first, ctrl->last) { 170 + xa_erase(xa, idx); 171 + 172 + /* Leak the descriptor when it is still referenced */ 173 + if (WARN_ON_ONCE(msi_desc_match(desc, MSI_DESC_ASSOCIATED))) 174 + continue; 175 + msi_free_desc(desc); 184 176 } 177 + } 178 + 179 + /** 180 + * msi_domain_free_msi_descs_range - Free a range of MSI descriptors of a device in an irqdomain 181 + * @dev: Device for which to free the descriptors 182 + * @domid: Id of the domain to operate on 183 + * @first: Index to start freeing from (inclusive) 184 + * @last: Last index to be freed (inclusive) 185 + */ 186 + void msi_domain_free_msi_descs_range(struct device *dev, unsigned int domid, 187 + unsigned int first, unsigned int last) 188 + { 189 + struct msi_ctrl ctrl = { 190 + .domid = domid, 191 + .first = first, 192 + .last = last, 193 + }; 194 + 195 + msi_domain_free_descs(dev, &ctrl); 196 + } 197 + 198 + /** 199 + * msi_domain_add_simple_msi_descs - Allocate and initialize MSI descriptors 200 + * @dev: Pointer to the device for which the descriptors are allocated 201 + * @ctrl: Allocation control struct 202 + * 203 + * Return: 0 on success or an appropriate failure code. 204 + */ 205 + static int msi_domain_add_simple_msi_descs(struct device *dev, struct msi_ctrl *ctrl) 206 + { 207 + struct msi_desc *desc; 208 + unsigned int idx; 209 + int ret; 210 + 211 + lockdep_assert_held(&dev->msi.data->mutex); 212 + 213 + if (!msi_ctrl_valid(dev, ctrl)) 214 + return -EINVAL; 215 + 216 + for (idx = ctrl->first; idx <= ctrl->last; idx++) { 217 + desc = msi_alloc_desc(dev, 1, NULL); 218 + if (!desc) 219 + goto fail_mem; 220 + ret = msi_insert_desc(dev, desc, ctrl->domid, idx); 221 + if (ret) 222 + goto fail; 223 + } 224 + return 0; 225 + 226 + fail_mem: 227 + ret = -ENOMEM; 228 + fail: 229 + msi_domain_free_descs(dev, ctrl); 230 + return ret; 185 231 } 186 232 187 233 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) ··· 268 178 static void msi_device_data_release(struct device *dev, void *res) 269 179 { 270 180 struct msi_device_data *md = res; 181 + int i; 271 182 272 - WARN_ON_ONCE(!xa_empty(&md->__store)); 273 - xa_destroy(&md->__store); 183 + for (i = 0; i < MSI_MAX_DEVICE_IRQDOMAINS; i++) { 184 + msi_remove_device_irq_domain(dev, i); 185 + WARN_ON_ONCE(!xa_empty(&md->__domains[i].store)); 186 + xa_destroy(&md->__domains[i].store); 187 + } 274 188 dev->msi.data = NULL; 275 189 } 276 190 ··· 291 197 int msi_setup_device_data(struct device *dev) 292 198 { 293 199 struct msi_device_data *md; 294 - int ret; 200 + int ret, i; 295 201 296 202 if (dev->msi.data) 297 203 return 0; ··· 306 212 return ret; 307 213 } 308 214 309 - xa_init(&md->__store); 215 + for (i = 0; i < MSI_MAX_DEVICE_IRQDOMAINS; i++) 216 + xa_init_flags(&md->__domains[i].store, XA_FLAGS_ALLOC); 217 + 218 + /* 219 + * If @dev::msi::domain is set and is a global MSI domain, copy the 220 + * pointer into the domain array so all code can operate on domain 221 + * ids. The NULL pointer check is required to keep the legacy 222 + * architecture specific PCI/MSI support working. 223 + */ 224 + if (dev->msi.domain && !irq_domain_is_msi_parent(dev->msi.domain)) 225 + md->__domains[MSI_DEFAULT_DOMAIN].domain = dev->msi.domain; 226 + 310 227 mutex_init(&md->mutex); 311 228 dev->msi.data = md; 312 229 devres_add(dev, md); ··· 340 235 */ 341 236 void msi_unlock_descs(struct device *dev) 342 237 { 343 - /* Invalidate the index wich was cached by the iterator */ 344 - dev->msi.data->__iter_idx = MSI_MAX_INDEX; 238 + /* Invalidate the index which was cached by the iterator */ 239 + dev->msi.data->__iter_idx = MSI_XA_MAX_INDEX; 345 240 mutex_unlock(&dev->msi.data->mutex); 346 241 } 347 242 EXPORT_SYMBOL_GPL(msi_unlock_descs); 348 243 349 - static struct msi_desc *msi_find_desc(struct msi_device_data *md, enum msi_desc_filter filter) 244 + static struct msi_desc *msi_find_desc(struct msi_device_data *md, unsigned int domid, 245 + enum msi_desc_filter filter) 350 246 { 247 + struct xarray *xa = &md->__domains[domid].store; 351 248 struct msi_desc *desc; 352 249 353 - xa_for_each_start(&md->__store, md->__iter_idx, desc, md->__iter_idx) { 250 + xa_for_each_start(xa, md->__iter_idx, desc, md->__iter_idx) { 354 251 if (msi_desc_match(desc, filter)) 355 252 return desc; 356 253 } 357 - md->__iter_idx = MSI_MAX_INDEX; 254 + md->__iter_idx = MSI_XA_MAX_INDEX; 358 255 return NULL; 359 256 } 360 257 361 258 /** 362 - * msi_first_desc - Get the first MSI descriptor of a device 259 + * msi_domain_first_desc - Get the first MSI descriptor of an irqdomain associated to a device 363 260 * @dev: Device to operate on 261 + * @domid: The id of the interrupt domain which should be walked. 364 262 * @filter: Descriptor state filter 365 263 * 366 264 * Must be called with the MSI descriptor mutex held, i.e. msi_lock_descs() ··· 372 264 * Return: Pointer to the first MSI descriptor matching the search 373 265 * criteria, NULL if none found. 374 266 */ 375 - struct msi_desc *msi_first_desc(struct device *dev, enum msi_desc_filter filter) 267 + struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, 268 + enum msi_desc_filter filter) 376 269 { 377 270 struct msi_device_data *md = dev->msi.data; 378 271 379 - if (WARN_ON_ONCE(!md)) 272 + if (WARN_ON_ONCE(!md || domid >= MSI_MAX_DEVICE_IRQDOMAINS)) 380 273 return NULL; 381 274 382 275 lockdep_assert_held(&md->mutex); 383 276 384 277 md->__iter_idx = 0; 385 - return msi_find_desc(md, filter); 278 + return msi_find_desc(md, domid, filter); 386 279 } 387 - EXPORT_SYMBOL_GPL(msi_first_desc); 280 + EXPORT_SYMBOL_GPL(msi_domain_first_desc); 388 281 389 282 /** 390 283 * msi_next_desc - Get the next MSI descriptor of a device 391 284 * @dev: Device to operate on 285 + * @domid: The id of the interrupt domain which should be walked. 286 + * @filter: Descriptor state filter 392 287 * 393 288 * The first invocation of msi_next_desc() has to be preceeded by a 394 289 * successful invocation of __msi_first_desc(). Consecutive invocations are ··· 401 290 * Return: Pointer to the next MSI descriptor matching the search 402 291 * criteria, NULL if none found. 403 292 */ 404 - struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter) 293 + struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, 294 + enum msi_desc_filter filter) 405 295 { 406 296 struct msi_device_data *md = dev->msi.data; 407 297 408 - if (WARN_ON_ONCE(!md)) 298 + if (WARN_ON_ONCE(!md || domid >= MSI_MAX_DEVICE_IRQDOMAINS)) 409 299 return NULL; 410 300 411 301 lockdep_assert_held(&md->mutex); ··· 415 303 return NULL; 416 304 417 305 md->__iter_idx++; 418 - return msi_find_desc(md, filter); 306 + return msi_find_desc(md, domid, filter); 419 307 } 420 308 EXPORT_SYMBOL_GPL(msi_next_desc); 421 309 422 310 /** 423 - * msi_get_virq - Return Linux interrupt number of a MSI interrupt 311 + * msi_domain_get_virq - Lookup the Linux interrupt number for a MSI index on a interrupt domain 424 312 * @dev: Device to operate on 313 + * @domid: Domain ID of the interrupt domain associated to the device 425 314 * @index: MSI interrupt index to look for (0-based) 426 315 * 427 316 * Return: The Linux interrupt number on success (> 0), 0 if not found 428 317 */ 429 - unsigned int msi_get_virq(struct device *dev, unsigned int index) 318 + unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index) 430 319 { 431 320 struct msi_desc *desc; 432 321 unsigned int ret = 0; 433 - bool pcimsi; 322 + bool pcimsi = false; 323 + struct xarray *xa; 434 324 435 325 if (!dev->msi.data) 436 326 return 0; 437 327 438 - pcimsi = dev_is_pci(dev) ? to_pci_dev(dev)->msi_enabled : false; 328 + if (WARN_ON_ONCE(index > MSI_MAX_INDEX || domid >= MSI_MAX_DEVICE_IRQDOMAINS)) 329 + return 0; 330 + 331 + /* This check is only valid for the PCI default MSI domain */ 332 + if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN) 333 + pcimsi = to_pci_dev(dev)->msi_enabled; 439 334 440 335 msi_lock_descs(dev); 441 - desc = xa_load(&dev->msi.data->__store, pcimsi ? 0 : index); 336 + xa = &dev->msi.data->__domains[domid].store; 337 + desc = xa_load(xa, pcimsi ? 0 : index); 442 338 if (desc && desc->irq) { 443 339 /* 444 340 * PCI-MSI has only one descriptor for multiple interrupts. ··· 460 340 ret = desc->irq; 461 341 } 462 342 } 343 + 463 344 msi_unlock_descs(dev); 464 345 return ret; 465 346 } 466 - EXPORT_SYMBOL_GPL(msi_get_virq); 347 + EXPORT_SYMBOL_GPL(msi_domain_get_virq); 467 348 468 349 #ifdef CONFIG_SYSFS 469 350 static struct attribute *msi_dev_attrs[] = { ··· 580 459 static inline void msi_sysfs_remove_desc(struct device *dev, struct msi_desc *desc) { } 581 460 #endif /* !CONFIG_SYSFS */ 582 461 583 - #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 462 + static struct irq_domain *msi_get_device_domain(struct device *dev, unsigned int domid) 463 + { 464 + struct irq_domain *domain; 465 + 466 + lockdep_assert_held(&dev->msi.data->mutex); 467 + 468 + if (WARN_ON_ONCE(domid >= MSI_MAX_DEVICE_IRQDOMAINS)) 469 + return NULL; 470 + 471 + domain = dev->msi.data->__domains[domid].domain; 472 + if (!domain) 473 + return NULL; 474 + 475 + if (WARN_ON_ONCE(irq_domain_is_msi_parent(domain))) 476 + return NULL; 477 + 478 + return domain; 479 + } 480 + 481 + static unsigned int msi_domain_get_hwsize(struct device *dev, unsigned int domid) 482 + { 483 + struct msi_domain_info *info; 484 + struct irq_domain *domain; 485 + 486 + domain = msi_get_device_domain(dev, domid); 487 + if (domain) { 488 + info = domain->host_data; 489 + return info->hwsize; 490 + } 491 + /* No domain, no size... */ 492 + return 0; 493 + } 494 + 584 495 static inline void irq_chip_write_msi_msg(struct irq_data *data, 585 496 struct msi_msg *msg) 586 497 { ··· 766 613 return 0; 767 614 } 768 615 769 - static int msi_domain_ops_check(struct irq_domain *domain, 770 - struct msi_domain_info *info, 771 - struct device *dev) 772 - { 773 - return 0; 774 - } 775 - 776 616 static struct msi_domain_ops msi_domain_ops_default = { 777 617 .get_hwirq = msi_domain_ops_get_hwirq, 778 618 .msi_init = msi_domain_ops_init, 779 - .msi_check = msi_domain_ops_check, 780 619 .msi_prepare = msi_domain_ops_prepare, 781 620 .set_desc = msi_domain_ops_set_desc, 782 - .domain_alloc_irqs = __msi_domain_alloc_irqs, 783 - .domain_free_irqs = __msi_domain_free_irqs, 784 621 }; 785 622 786 623 static void msi_domain_update_dom_ops(struct msi_domain_info *info) ··· 782 639 return; 783 640 } 784 641 785 - if (ops->domain_alloc_irqs == NULL) 786 - ops->domain_alloc_irqs = msi_domain_ops_default.domain_alloc_irqs; 787 - if (ops->domain_free_irqs == NULL) 788 - ops->domain_free_irqs = msi_domain_ops_default.domain_free_irqs; 789 - 790 642 if (!(info->flags & MSI_FLAG_USE_DEF_DOM_OPS)) 791 643 return; 792 644 ··· 789 651 ops->get_hwirq = msi_domain_ops_default.get_hwirq; 790 652 if (ops->msi_init == NULL) 791 653 ops->msi_init = msi_domain_ops_default.msi_init; 792 - if (ops->msi_check == NULL) 793 - ops->msi_check = msi_domain_ops_default.msi_check; 794 654 if (ops->msi_prepare == NULL) 795 655 ops->msi_prepare = msi_domain_ops_default.msi_prepare; 796 656 if (ops->set_desc == NULL) ··· 804 668 chip->irq_set_affinity = msi_domain_set_affinity; 805 669 } 806 670 671 + static struct irq_domain *__msi_create_irq_domain(struct fwnode_handle *fwnode, 672 + struct msi_domain_info *info, 673 + unsigned int flags, 674 + struct irq_domain *parent) 675 + { 676 + struct irq_domain *domain; 677 + 678 + if (info->hwsize > MSI_XA_DOMAIN_SIZE) 679 + return NULL; 680 + 681 + /* 682 + * Hardware size 0 is valid for backwards compatibility and for 683 + * domains which are not backed by a hardware table. Grant the 684 + * maximum index space. 685 + */ 686 + if (!info->hwsize) 687 + info->hwsize = MSI_XA_DOMAIN_SIZE; 688 + 689 + msi_domain_update_dom_ops(info); 690 + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) 691 + msi_domain_update_chip_ops(info); 692 + 693 + domain = irq_domain_create_hierarchy(parent, flags | IRQ_DOMAIN_FLAG_MSI, 0, 694 + fwnode, &msi_domain_ops, info); 695 + 696 + if (domain) { 697 + if (!domain->name && info->chip) 698 + domain->name = info->chip->name; 699 + irq_domain_update_bus_token(domain, info->bus_token); 700 + } 701 + 702 + return domain; 703 + } 704 + 807 705 /** 808 706 * msi_create_irq_domain - Create an MSI interrupt domain 809 707 * @fwnode: Optional fwnode of the interrupt controller ··· 850 680 struct msi_domain_info *info, 851 681 struct irq_domain *parent) 852 682 { 683 + return __msi_create_irq_domain(fwnode, info, 0, parent); 684 + } 685 + 686 + /** 687 + * msi_parent_init_dev_msi_info - Delegate initialization of device MSI info down 688 + * in the domain hierarchy 689 + * @dev: The device for which the domain should be created 690 + * @domain: The domain in the hierarchy this op is being called on 691 + * @msi_parent_domain: The IRQ_DOMAIN_FLAG_MSI_PARENT domain for the child to 692 + * be created 693 + * @msi_child_info: The MSI domain info of the IRQ_DOMAIN_FLAG_MSI_DEVICE 694 + * domain to be created 695 + * 696 + * Return: true on success, false otherwise 697 + * 698 + * This is the most complex problem of per device MSI domains and the 699 + * underlying interrupt domain hierarchy: 700 + * 701 + * The device domain to be initialized requests the broadest feature set 702 + * possible and the underlying domain hierarchy puts restrictions on it. 703 + * 704 + * That's trivial for a simple parent->child relationship, but it gets 705 + * interesting with an intermediate domain: root->parent->child. The 706 + * intermediate 'parent' can expand the capabilities which the 'root' 707 + * domain is providing. So that creates a classic hen and egg problem: 708 + * Which entity is doing the restrictions/expansions? 709 + * 710 + * One solution is to let the root domain handle the initialization that's 711 + * why there is the @domain and the @msi_parent_domain pointer. 712 + */ 713 + bool msi_parent_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 714 + struct irq_domain *msi_parent_domain, 715 + struct msi_domain_info *msi_child_info) 716 + { 717 + struct irq_domain *parent = domain->parent; 718 + 719 + if (WARN_ON_ONCE(!parent || !parent->msi_parent_ops || 720 + !parent->msi_parent_ops->init_dev_msi_info)) 721 + return false; 722 + 723 + return parent->msi_parent_ops->init_dev_msi_info(dev, parent, msi_parent_domain, 724 + msi_child_info); 725 + } 726 + 727 + /** 728 + * msi_create_device_irq_domain - Create a device MSI interrupt domain 729 + * @dev: Pointer to the device 730 + * @domid: Domain id 731 + * @template: MSI domain info bundle used as template 732 + * @hwsize: Maximum number of MSI table entries (0 if unknown or unlimited) 733 + * @domain_data: Optional pointer to domain specific data which is set in 734 + * msi_domain_info::data 735 + * @chip_data: Optional pointer to chip specific data which is set in 736 + * msi_domain_info::chip_data 737 + * 738 + * Return: True on success, false otherwise 739 + * 740 + * There is no firmware node required for this interface because the per 741 + * device domains are software constructs which are actually closer to the 742 + * hardware reality than any firmware can describe them. 743 + * 744 + * The domain name and the irq chip name for a MSI device domain are 745 + * composed by: "$(PREFIX)$(CHIPNAME)-$(DEVNAME)" 746 + * 747 + * $PREFIX: Optional prefix provided by the underlying MSI parent domain 748 + * via msi_parent_ops::prefix. If that pointer is NULL the prefix 749 + * is empty. 750 + * $CHIPNAME: The name of the irq_chip in @template 751 + * $DEVNAME: The name of the device 752 + * 753 + * This results in understandable chip names and hardware interrupt numbers 754 + * in e.g. /proc/interrupts 755 + * 756 + * PCI-MSI-0000:00:1c.0 0-edge Parent domain has no prefix 757 + * IR-PCI-MSI-0000:00:1c.4 0-edge Same with interrupt remapping prefix 'IR-' 758 + * 759 + * IR-PCI-MSIX-0000:3d:00.0 0-edge Hardware interrupt numbers reflect 760 + * IR-PCI-MSIX-0000:3d:00.0 1-edge the real MSI-X index on that device 761 + * IR-PCI-MSIX-0000:3d:00.0 2-edge 762 + * 763 + * On IMS domains the hardware interrupt number is either a table entry 764 + * index or a purely software managed index but it is guaranteed to be 765 + * unique. 766 + * 767 + * The domain pointer is stored in @dev::msi::data::__irqdomains[]. All 768 + * subsequent operations on the domain depend on the domain id. 769 + * 770 + * The domain is automatically freed when the device is removed via devres 771 + * in the context of @dev::msi::data freeing, but it can also be 772 + * independently removed via @msi_remove_device_irq_domain(). 773 + */ 774 + bool msi_create_device_irq_domain(struct device *dev, unsigned int domid, 775 + const struct msi_domain_template *template, 776 + unsigned int hwsize, void *domain_data, 777 + void *chip_data) 778 + { 779 + struct irq_domain *domain, *parent = dev->msi.domain; 780 + const struct msi_parent_ops *pops; 781 + struct msi_domain_template *bundle; 782 + struct fwnode_handle *fwnode; 783 + 784 + if (!irq_domain_is_msi_parent(parent)) 785 + return false; 786 + 787 + if (domid >= MSI_MAX_DEVICE_IRQDOMAINS) 788 + return false; 789 + 790 + bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL); 791 + if (!bundle) 792 + return false; 793 + 794 + bundle->info.hwsize = hwsize; 795 + bundle->info.chip = &bundle->chip; 796 + bundle->info.ops = &bundle->ops; 797 + bundle->info.data = domain_data; 798 + bundle->info.chip_data = chip_data; 799 + 800 + pops = parent->msi_parent_ops; 801 + snprintf(bundle->name, sizeof(bundle->name), "%s%s-%s", 802 + pops->prefix ? : "", bundle->chip.name, dev_name(dev)); 803 + bundle->chip.name = bundle->name; 804 + 805 + fwnode = irq_domain_alloc_named_fwnode(bundle->name); 806 + if (!fwnode) 807 + goto free_bundle; 808 + 809 + if (msi_setup_device_data(dev)) 810 + goto free_fwnode; 811 + 812 + msi_lock_descs(dev); 813 + 814 + if (WARN_ON_ONCE(msi_get_device_domain(dev, domid))) 815 + goto fail; 816 + 817 + if (!pops->init_dev_msi_info(dev, parent, parent, &bundle->info)) 818 + goto fail; 819 + 820 + domain = __msi_create_irq_domain(fwnode, &bundle->info, IRQ_DOMAIN_FLAG_MSI_DEVICE, parent); 821 + if (!domain) 822 + goto fail; 823 + 824 + domain->dev = dev; 825 + dev->msi.data->__domains[domid].domain = domain; 826 + msi_unlock_descs(dev); 827 + return true; 828 + 829 + fail: 830 + msi_unlock_descs(dev); 831 + free_fwnode: 832 + kfree(fwnode); 833 + free_bundle: 834 + kfree(bundle); 835 + return false; 836 + } 837 + 838 + /** 839 + * msi_remove_device_irq_domain - Free a device MSI interrupt domain 840 + * @dev: Pointer to the device 841 + * @domid: Domain id 842 + */ 843 + void msi_remove_device_irq_domain(struct device *dev, unsigned int domid) 844 + { 845 + struct msi_domain_info *info; 853 846 struct irq_domain *domain; 854 847 855 - msi_domain_update_dom_ops(info); 856 - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) 857 - msi_domain_update_chip_ops(info); 848 + msi_lock_descs(dev); 858 849 859 - domain = irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0, 860 - fwnode, &msi_domain_ops, info); 850 + domain = msi_get_device_domain(dev, domid); 861 851 862 - if (domain && !domain->name && info->chip) 863 - domain->name = info->chip->name; 852 + if (!domain || !irq_domain_is_msi_device(domain)) 853 + goto unlock; 864 854 865 - return domain; 855 + dev->msi.data->__domains[domid].domain = NULL; 856 + info = domain->host_data; 857 + irq_domain_remove(domain); 858 + kfree(container_of(info, struct msi_domain_template, info)); 859 + 860 + unlock: 861 + msi_unlock_descs(dev); 862 + } 863 + 864 + /** 865 + * msi_match_device_irq_domain - Match a device irq domain against a bus token 866 + * @dev: Pointer to the device 867 + * @domid: Domain id 868 + * @bus_token: Bus token to match against the domain bus token 869 + * 870 + * Return: True if device domain exists and bus tokens match. 871 + */ 872 + bool msi_match_device_irq_domain(struct device *dev, unsigned int domid, 873 + enum irq_domain_bus_token bus_token) 874 + { 875 + struct msi_domain_info *info; 876 + struct irq_domain *domain; 877 + bool ret = false; 878 + 879 + msi_lock_descs(dev); 880 + domain = msi_get_device_domain(dev, domid); 881 + if (domain && irq_domain_is_msi_device(domain)) { 882 + info = domain->host_data; 883 + ret = info->bus_token == bus_token; 884 + } 885 + msi_unlock_descs(dev); 886 + return ret; 866 887 } 867 888 868 889 int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, ··· 1061 700 { 1062 701 struct msi_domain_info *info = domain->host_data; 1063 702 struct msi_domain_ops *ops = info->ops; 1064 - int ret; 1065 703 1066 - ret = ops->msi_check(domain, info, dev); 1067 - if (ret == 0) 1068 - ret = ops->msi_prepare(domain, dev, nvec, arg); 1069 - 1070 - return ret; 704 + return ops->msi_prepare(domain, dev, nvec, arg); 1071 705 } 1072 706 1073 707 int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, ··· 1070 714 { 1071 715 struct msi_domain_info *info = domain->host_data; 1072 716 struct msi_domain_ops *ops = info->ops; 717 + struct msi_ctrl ctrl = { 718 + .domid = MSI_DEFAULT_DOMAIN, 719 + .first = virq_base, 720 + .last = virq_base + nvec - 1, 721 + }; 1073 722 struct msi_desc *desc; 723 + struct xarray *xa; 1074 724 int ret, virq; 1075 725 726 + if (!msi_ctrl_valid(dev, &ctrl)) 727 + return -EINVAL; 728 + 1076 729 msi_lock_descs(dev); 1077 - ret = msi_add_simple_msi_descs(dev, virq_base, nvec); 730 + ret = msi_domain_add_simple_msi_descs(dev, &ctrl); 1078 731 if (ret) 1079 732 goto unlock; 1080 733 734 + xa = &dev->msi.data->__domains[ctrl.domid].store; 735 + 1081 736 for (virq = virq_base; virq < virq_base + nvec; virq++) { 1082 - desc = xa_load(&dev->msi.data->__store, virq); 737 + desc = xa_load(xa, virq); 1083 738 desc->irq = virq; 1084 739 1085 740 ops->set_desc(arg, desc); ··· 1106 739 fail: 1107 740 for (--virq; virq >= virq_base; virq--) 1108 741 irq_domain_free_irqs_common(domain, virq, 1); 1109 - msi_free_msi_descs_range(dev, MSI_DESC_ALL, virq_base, virq_base + nvec - 1); 742 + msi_domain_free_descs(dev, &ctrl); 1110 743 unlock: 1111 744 msi_unlock_descs(dev); 1112 745 return ret; ··· 1131 764 1132 765 switch(domain->bus_token) { 1133 766 case DOMAIN_BUS_PCI_MSI: 767 + case DOMAIN_BUS_PCI_DEVICE_MSI: 768 + case DOMAIN_BUS_PCI_DEVICE_MSIX: 1134 769 case DOMAIN_BUS_VMD_MSI: 1135 770 break; 1136 771 default: ··· 1158 789 { 1159 790 switch(domain->bus_token) { 1160 791 case DOMAIN_BUS_PCI_MSI: 792 + case DOMAIN_BUS_PCI_DEVICE_MSI: 793 + case DOMAIN_BUS_PCI_DEVICE_MSIX: 1161 794 case DOMAIN_BUS_VMD_MSI: 1162 795 if (IS_ENABLED(CONFIG_PCI_MSI)) 1163 796 break; ··· 1221 850 return 0; 1222 851 } 1223 852 1224 - int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, 1225 - int nvec) 853 + static int __msi_domain_alloc_irqs(struct device *dev, struct irq_domain *domain, 854 + struct msi_ctrl *ctrl) 1226 855 { 856 + struct xarray *xa = &dev->msi.data->__domains[ctrl->domid].store; 1227 857 struct msi_domain_info *info = domain->host_data; 1228 858 struct msi_domain_ops *ops = info->ops; 859 + unsigned int vflags = 0, allocated = 0; 1229 860 msi_alloc_info_t arg = { }; 1230 - unsigned int vflags = 0; 1231 861 struct msi_desc *desc; 1232 - int allocated = 0; 862 + unsigned long idx; 1233 863 int i, ret, virq; 1234 864 1235 - ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); 865 + ret = msi_domain_prepare_irqs(domain, dev, ctrl->nirqs, &arg); 1236 866 if (ret) 1237 867 return ret; 1238 868 ··· 1255 883 * MSI affinity setting requires a special quirk (X86) when 1256 884 * reservation mode is active. 1257 885 */ 1258 - if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) 886 + if (info->flags & MSI_FLAG_NOMASK_QUIRK) 1259 887 vflags |= VIRQ_NOMASK_QUIRK; 1260 888 } 1261 889 1262 - msi_for_each_desc(desc, dev, MSI_DESC_NOTASSOCIATED) { 890 + xa_for_each_range(xa, idx, desc, ctrl->first, ctrl->last) { 891 + if (!msi_desc_match(desc, MSI_DESC_NOTASSOCIATED)) 892 + continue; 893 + 894 + /* This should return -ECONFUSED... */ 895 + if (WARN_ON_ONCE(allocated >= ctrl->nirqs)) 896 + return -EINVAL; 897 + 898 + if (ops->prepare_desc) 899 + ops->prepare_desc(domain, &arg, desc); 900 + 1263 901 ops->set_desc(&arg, desc); 1264 902 1265 903 virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used, ··· 1295 913 return 0; 1296 914 } 1297 915 1298 - static int msi_domain_add_simple_msi_descs(struct msi_domain_info *info, 1299 - struct device *dev, 1300 - unsigned int num_descs) 916 + static int msi_domain_alloc_simple_msi_descs(struct device *dev, 917 + struct msi_domain_info *info, 918 + struct msi_ctrl *ctrl) 1301 919 { 1302 920 if (!(info->flags & MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS)) 1303 921 return 0; 1304 922 1305 - return msi_add_simple_msi_descs(dev, 0, num_descs); 923 + return msi_domain_add_simple_msi_descs(dev, ctrl); 924 + } 925 + 926 + static int __msi_domain_alloc_locked(struct device *dev, struct msi_ctrl *ctrl) 927 + { 928 + struct msi_domain_info *info; 929 + struct msi_domain_ops *ops; 930 + struct irq_domain *domain; 931 + int ret; 932 + 933 + if (!msi_ctrl_valid(dev, ctrl)) 934 + return -EINVAL; 935 + 936 + domain = msi_get_device_domain(dev, ctrl->domid); 937 + if (!domain) 938 + return -ENODEV; 939 + 940 + info = domain->host_data; 941 + 942 + ret = msi_domain_alloc_simple_msi_descs(dev, info, ctrl); 943 + if (ret) 944 + return ret; 945 + 946 + ops = info->ops; 947 + if (ops->domain_alloc_irqs) 948 + return ops->domain_alloc_irqs(domain, dev, ctrl->nirqs); 949 + 950 + return __msi_domain_alloc_irqs(dev, domain, ctrl); 951 + } 952 + 953 + static int msi_domain_alloc_locked(struct device *dev, struct msi_ctrl *ctrl) 954 + { 955 + int ret = __msi_domain_alloc_locked(dev, ctrl); 956 + 957 + if (ret) 958 + msi_domain_free_locked(dev, ctrl); 959 + return ret; 1306 960 } 1307 961 1308 962 /** 1309 - * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain 1310 - * @domain: The domain to allocate from 963 + * msi_domain_alloc_irqs_range_locked - Allocate interrupts from a MSI interrupt domain 1311 964 * @dev: Pointer to device struct of the device for which the interrupts 1312 965 * are allocated 1313 - * @nvec: The number of interrupts to allocate 966 + * @domid: Id of the interrupt domain to operate on 967 + * @first: First index to allocate (inclusive) 968 + * @last: Last index to allocate (inclusive) 1314 969 * 1315 970 * Must be invoked from within a msi_lock_descs() / msi_unlock_descs() 1316 - * pair. Use this for MSI irqdomains which implement their own vector 971 + * pair. Use this for MSI irqdomains which implement their own descriptor 1317 972 * allocation/free. 1318 973 * 1319 974 * Return: %0 on success or an error code. 1320 975 */ 1321 - int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev, 1322 - int nvec) 976 + int msi_domain_alloc_irqs_range_locked(struct device *dev, unsigned int domid, 977 + unsigned int first, unsigned int last) 1323 978 { 1324 - struct msi_domain_info *info = domain->host_data; 1325 - struct msi_domain_ops *ops = info->ops; 1326 - int ret; 979 + struct msi_ctrl ctrl = { 980 + .domid = domid, 981 + .first = first, 982 + .last = last, 983 + .nirqs = last + 1 - first, 984 + }; 1327 985 1328 - lockdep_assert_held(&dev->msi.data->mutex); 1329 - 1330 - ret = msi_domain_add_simple_msi_descs(info, dev, nvec); 1331 - if (ret) 1332 - return ret; 1333 - 1334 - ret = ops->domain_alloc_irqs(domain, dev, nvec); 1335 - if (ret) 1336 - msi_domain_free_irqs_descs_locked(domain, dev); 1337 - return ret; 986 + return msi_domain_alloc_locked(dev, &ctrl); 1338 987 } 1339 988 1340 989 /** 1341 - * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain 1342 - * @domain: The domain to allocate from 990 + * msi_domain_alloc_irqs_range - Allocate interrupts from a MSI interrupt domain 1343 991 * @dev: Pointer to device struct of the device for which the interrupts 1344 992 * are allocated 1345 - * @nvec: The number of interrupts to allocate 993 + * @domid: Id of the interrupt domain to operate on 994 + * @first: First index to allocate (inclusive) 995 + * @last: Last index to allocate (inclusive) 1346 996 * 1347 997 * Return: %0 on success or an error code. 1348 998 */ 1349 - int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec) 999 + int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, 1000 + unsigned int first, unsigned int last) 1350 1001 { 1351 1002 int ret; 1352 1003 1353 1004 msi_lock_descs(dev); 1354 - ret = msi_domain_alloc_irqs_descs_locked(domain, dev, nvec); 1005 + ret = msi_domain_alloc_irqs_range_locked(dev, domid, first, last); 1355 1006 msi_unlock_descs(dev); 1356 1007 return ret; 1357 1008 } 1358 1009 1359 - void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) 1010 + /** 1011 + * msi_domain_alloc_irqs_all_locked - Allocate all interrupts from a MSI interrupt domain 1012 + * 1013 + * @dev: Pointer to device struct of the device for which the interrupts 1014 + * are allocated 1015 + * @domid: Id of the interrupt domain to operate on 1016 + * @nirqs: The number of interrupts to allocate 1017 + * 1018 + * This function scans all MSI descriptors of the MSI domain and allocates interrupts 1019 + * for all unassigned ones. That function is to be used for MSI domain usage where 1020 + * the descriptor allocation is handled at the call site, e.g. PCI/MSI[X]. 1021 + * 1022 + * Return: %0 on success or an error code. 1023 + */ 1024 + int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int nirqs) 1360 1025 { 1026 + struct msi_ctrl ctrl = { 1027 + .domid = domid, 1028 + .first = 0, 1029 + .last = msi_domain_get_hwsize(dev, domid) - 1, 1030 + .nirqs = nirqs, 1031 + }; 1032 + 1033 + return msi_domain_alloc_locked(dev, &ctrl); 1034 + } 1035 + 1036 + /** 1037 + * msi_domain_alloc_irq_at - Allocate an interrupt from a MSI interrupt domain at 1038 + * a given index - or at the next free index 1039 + * 1040 + * @dev: Pointer to device struct of the device for which the interrupts 1041 + * are allocated 1042 + * @domid: Id of the interrupt domain to operate on 1043 + * @index: Index for allocation. If @index == %MSI_ANY_INDEX the allocation 1044 + * uses the next free index. 1045 + * @affdesc: Optional pointer to an interrupt affinity descriptor structure 1046 + * @icookie: Optional pointer to a domain specific per instance cookie. If 1047 + * non-NULL the content of the cookie is stored in msi_desc::data. 1048 + * Must be NULL for MSI-X allocations 1049 + * 1050 + * This requires a MSI interrupt domain which lets the core code manage the 1051 + * MSI descriptors. 1052 + * 1053 + * Return: struct msi_map 1054 + * 1055 + * On success msi_map::index contains the allocated index number and 1056 + * msi_map::virq the corresponding Linux interrupt number 1057 + * 1058 + * On failure msi_map::index contains the error code and msi_map::virq 1059 + * is %0. 1060 + */ 1061 + struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index, 1062 + const struct irq_affinity_desc *affdesc, 1063 + union msi_instance_cookie *icookie) 1064 + { 1065 + struct msi_ctrl ctrl = { .domid = domid, .nirqs = 1, }; 1066 + struct irq_domain *domain; 1067 + struct msi_map map = { }; 1068 + struct msi_desc *desc; 1069 + int ret; 1070 + 1071 + msi_lock_descs(dev); 1072 + domain = msi_get_device_domain(dev, domid); 1073 + if (!domain) { 1074 + map.index = -ENODEV; 1075 + goto unlock; 1076 + } 1077 + 1078 + desc = msi_alloc_desc(dev, 1, affdesc); 1079 + if (!desc) { 1080 + map.index = -ENOMEM; 1081 + goto unlock; 1082 + } 1083 + 1084 + if (icookie) 1085 + desc->data.icookie = *icookie; 1086 + 1087 + ret = msi_insert_desc(dev, desc, domid, index); 1088 + if (ret) { 1089 + map.index = ret; 1090 + goto unlock; 1091 + } 1092 + 1093 + ctrl.first = ctrl.last = desc->msi_index; 1094 + 1095 + ret = __msi_domain_alloc_irqs(dev, domain, &ctrl); 1096 + if (ret) { 1097 + map.index = ret; 1098 + msi_domain_free_locked(dev, &ctrl); 1099 + } else { 1100 + map.index = desc->msi_index; 1101 + map.virq = desc->irq; 1102 + } 1103 + unlock: 1104 + msi_unlock_descs(dev); 1105 + return map; 1106 + } 1107 + 1108 + static void __msi_domain_free_irqs(struct device *dev, struct irq_domain *domain, 1109 + struct msi_ctrl *ctrl) 1110 + { 1111 + struct xarray *xa = &dev->msi.data->__domains[ctrl->domid].store; 1361 1112 struct msi_domain_info *info = domain->host_data; 1362 1113 struct irq_data *irqd; 1363 1114 struct msi_desc *desc; 1115 + unsigned long idx; 1364 1116 int i; 1365 1117 1366 - /* Only handle MSI entries which have an interrupt associated */ 1367 - msi_for_each_desc(desc, dev, MSI_DESC_ASSOCIATED) { 1118 + xa_for_each_range(xa, idx, desc, ctrl->first, ctrl->last) { 1119 + /* Only handle MSI entries which have an interrupt associated */ 1120 + if (!msi_desc_match(desc, MSI_DESC_ASSOCIATED)) 1121 + continue; 1122 + 1368 1123 /* Make sure all interrupts are deactivated */ 1369 1124 for (i = 0; i < desc->nvec_used; i++) { 1370 1125 irqd = irq_domain_get_irq_data(domain, desc->irq + i); ··· 1516 997 } 1517 998 } 1518 999 1519 - static void msi_domain_free_msi_descs(struct msi_domain_info *info, 1520 - struct device *dev) 1000 + static void msi_domain_free_locked(struct device *dev, struct msi_ctrl *ctrl) 1521 1001 { 1002 + struct msi_domain_info *info; 1003 + struct msi_domain_ops *ops; 1004 + struct irq_domain *domain; 1005 + 1006 + if (!msi_ctrl_valid(dev, ctrl)) 1007 + return; 1008 + 1009 + domain = msi_get_device_domain(dev, ctrl->domid); 1010 + if (!domain) 1011 + return; 1012 + 1013 + info = domain->host_data; 1014 + ops = info->ops; 1015 + 1016 + if (ops->domain_free_irqs) 1017 + ops->domain_free_irqs(domain, dev); 1018 + else 1019 + __msi_domain_free_irqs(dev, domain, ctrl); 1020 + 1021 + if (ops->msi_post_free) 1022 + ops->msi_post_free(domain, dev); 1023 + 1522 1024 if (info->flags & MSI_FLAG_FREE_MSI_DESCS) 1523 - msi_free_msi_descs(dev); 1025 + msi_domain_free_descs(dev, ctrl); 1524 1026 } 1525 1027 1526 1028 /** 1527 - * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev 1528 - * @domain: The domain to managing the interrupts 1029 + * msi_domain_free_irqs_range_locked - Free a range of interrupts from a MSI interrupt domain 1030 + * associated to @dev with msi_lock held 1529 1031 * @dev: Pointer to device struct of the device for which the interrupts 1530 - * are free 1032 + * are freed 1033 + * @domid: Id of the interrupt domain to operate on 1034 + * @first: First index to free (inclusive) 1035 + * @last: Last index to free (inclusive) 1036 + */ 1037 + void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, 1038 + unsigned int first, unsigned int last) 1039 + { 1040 + struct msi_ctrl ctrl = { 1041 + .domid = domid, 1042 + .first = first, 1043 + .last = last, 1044 + }; 1045 + msi_domain_free_locked(dev, &ctrl); 1046 + } 1047 + 1048 + /** 1049 + * msi_domain_free_irqs_range - Free a range of interrupts from a MSI interrupt domain 1050 + * associated to @dev 1051 + * @dev: Pointer to device struct of the device for which the interrupts 1052 + * are freed 1053 + * @domid: Id of the interrupt domain to operate on 1054 + * @first: First index to free (inclusive) 1055 + * @last: Last index to free (inclusive) 1056 + */ 1057 + void msi_domain_free_irqs_range(struct device *dev, unsigned int domid, 1058 + unsigned int first, unsigned int last) 1059 + { 1060 + msi_lock_descs(dev); 1061 + msi_domain_free_irqs_range_locked(dev, domid, first, last); 1062 + msi_unlock_descs(dev); 1063 + } 1064 + 1065 + /** 1066 + * msi_domain_free_irqs_all_locked - Free all interrupts from a MSI interrupt domain 1067 + * associated to a device 1068 + * @dev: Pointer to device struct of the device for which the interrupts 1069 + * are freed 1070 + * @domid: The id of the domain to operate on 1531 1071 * 1532 1072 * Must be invoked from within a msi_lock_descs() / msi_unlock_descs() 1533 1073 * pair. Use this for MSI irqdomains which implement their own vector 1534 1074 * allocation. 1535 1075 */ 1536 - void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev) 1076 + void msi_domain_free_irqs_all_locked(struct device *dev, unsigned int domid) 1537 1077 { 1538 - struct msi_domain_info *info = domain->host_data; 1539 - struct msi_domain_ops *ops = info->ops; 1540 - 1541 - lockdep_assert_held(&dev->msi.data->mutex); 1542 - 1543 - ops->domain_free_irqs(domain, dev); 1544 - msi_domain_free_msi_descs(info, dev); 1078 + msi_domain_free_irqs_range_locked(dev, domid, 0, 1079 + msi_domain_get_hwsize(dev, domid) - 1); 1545 1080 } 1546 1081 1547 1082 /** 1548 - * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated to @dev 1549 - * @domain: The domain to managing the interrupts 1083 + * msi_domain_free_irqs_all - Free all interrupts from a MSI interrupt domain 1084 + * associated to a device 1550 1085 * @dev: Pointer to device struct of the device for which the interrupts 1551 - * are free 1086 + * are freed 1087 + * @domid: The id of the domain to operate on 1552 1088 */ 1553 - void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) 1089 + void msi_domain_free_irqs_all(struct device *dev, unsigned int domid) 1554 1090 { 1555 1091 msi_lock_descs(dev); 1556 - msi_domain_free_irqs_descs_locked(domain, dev); 1092 + msi_domain_free_irqs_all_locked(dev, domid); 1557 1093 msi_unlock_descs(dev); 1558 1094 } 1559 1095 ··· 1622 1048 { 1623 1049 return (struct msi_domain_info *)domain->host_data; 1624 1050 } 1625 - 1626 - #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */