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

Configure Feed

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

Merge tag 'irq-msi-2025-05-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull MSI updates from Thomas Gleixner:
"Updates for the MSI subsystem (core code and PCI):

- Switch the MSI descriptor locking to lock guards

- Replace a broken and naive implementation of PCI/MSI-X control word
updates in the PCI/TPH driver with a properly serialized variant in
the PCI/MSI core code.

- Remove the MSI descriptor abuse in the SCCI/UFS/QCOM driver by
replacing the direct access to the MSI descriptors with the proper
API function calls. People will never understand that APIs exist
for a reason...

- Provide core infrastructre for the upcoming PCI endpoint library
extensions. Currently limited to ARM GICv3+, but in theory
extensible to other architectures.

- Provide a MSI domain::teardown() callback, which allows drivers to
undo the effects of the prepare() callback.

- Move the MSI domain::prepare() callback invocation to domain
creation time to avoid redundant (and in case of ARM/GIC-V3-ITS
confusing) invocations on every allocation.

In combination with the new teardown callback this removes some
ugly hacks in the GIC-V3-ITS driver, which pretended to work around
the short comings of the core code so far. With this update the
code is correct by design and implementation.

- Make the irqchip MSI library globally available, provide a MSI
parent domain creation helper and convert a bunch of (PCI/)MSI
drivers over to the modern MSI parent mechanism. This is the first
step to get rid of at least one incarnation of the three PCI/MSI
management schemes.

- The usual small cleanups and improvements"

* tag 'irq-msi-2025-05-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (33 commits)
PCI/MSI: Use bool for MSI enable state tracking
PCI: tegra: Convert to MSI parent infrastructure
PCI: xgene: Convert to MSI parent infrastructure
PCI: apple: Convert to MSI parent infrastructure
irqchip/msi-lib: Honour the MSI_FLAG_NO_AFFINITY flag
irqchip/mvebu: Convert to msi_create_parent_irq_domain() helper
irqchip/gic: Convert to msi_create_parent_irq_domain() helper
genirq/msi: Add helper for creating MSI-parent irq domains
irqchip: Make irq-msi-lib.h globally available
irqchip/gic-v3-its: Use allocation size from the prepare call
genirq/msi: Engage the .msi_teardown() callback on domain removal
genirq/msi: Move prepare() call to per-device allocation
irqchip/gic-v3-its: Implement .msi_teardown() callback
genirq/msi: Add .msi_teardown() callback as the reverse of .msi_prepare()
irqchip/gic-v3-its: Add support for device tree msi-map and msi-mask
dt-bindings: PCI: pci-ep: Add support for iommu-map and msi-map
irqchip/gic-v3-its: Set IRQ_DOMAIN_FLAG_MSI_IMMUTABLE for ITS
irqdomain: Add IRQ_DOMAIN_FLAG_MSI_IMMUTABLE and irq_domain_is_msi_immutable()
platform-msi: Add msi_remove_device_irq_domain() in platform_device_msi_free_irqs_all()
genirq/msi: Rename msi_[un]lock_descs()
...

+606 -520
+68
Documentation/devicetree/bindings/pci/pci-ep.yaml
··· 17 17 $nodename: 18 18 pattern: "^pcie-ep@" 19 19 20 + iommu-map: 21 + $ref: /schemas/types.yaml#/definitions/uint32-matrix 22 + items: 23 + items: 24 + - description: Device ID (see msi-map) base 25 + maximum: 0x7ffff 26 + - description: phandle to IOMMU 27 + - description: IOMMU specifier base (currently always 1 cell) 28 + - description: Number of Device IDs 29 + maximum: 0x80000 30 + 31 + iommu-map-mask: 32 + description: 33 + A mask to be applied to each Device ID prior to being mapped to an 34 + IOMMU specifier per the iommu-map property. 35 + $ref: /schemas/types.yaml#/definitions/uint32 36 + maximum: 0x7ffff 37 + 20 38 max-functions: 21 39 description: Maximum number of functions that can be configured 22 40 $ref: /schemas/types.yaml#/definitions/uint8 ··· 52 34 max-link-speed: 53 35 $ref: /schemas/types.yaml#/definitions/uint32 54 36 enum: [ 1, 2, 3, 4 ] 37 + 38 + msi-map: 39 + description: | 40 + Maps a Device ID to an MSI and associated MSI specifier data. 41 + 42 + A PCI Endpoint (EP) can use MSI as a doorbell function. This is achieved by 43 + mapping the MSI controller's address into PCI BAR<n>. The PCI Root Complex 44 + can write to this BAR<n>, triggering the EP to generate IRQ. This notifies 45 + the EP-side driver of an event, eliminating the need for the driver to 46 + continuously poll for status changes. 47 + 48 + However, the EP cannot rely on Requester ID (RID) because the RID is 49 + determined by the PCI topology of the host system. Since the EP may be 50 + connected to different PCI hosts, the RID can vary between systems and is 51 + therefore not a reliable identifier. 52 + 53 + Each EP can support up to 8 physical functions and up to 65,536 virtual 54 + functions. To uniquely identify each child device, a device ID is defined 55 + as 56 + - Bits [2:0] for the function number (func) 57 + - Bits [18:3] for the virtual function index (vfunc) 58 + 59 + The resulting device ID is computed as: 60 + 61 + (func & 0x7) | (vfunc << 3) 62 + 63 + The property is an arbitrary number of tuples of 64 + (device-id-base, msi, msi-base,length). 65 + 66 + Any Device ID id in the interval [id-base, id-base + length) is 67 + associated with the listed MSI, with the MSI specifier 68 + (id - id-base + msi-base). 69 + $ref: /schemas/types.yaml#/definitions/uint32-matrix 70 + items: 71 + items: 72 + - description: The Device ID base matched by the entry 73 + maximum: 0x7ffff 74 + - description: phandle to msi-controller node 75 + - description: (optional) The msi-specifier produced for the first 76 + Device ID matched by the entry. Currently, msi-specifier is 0 or 77 + 1 cells. 78 + - description: The length of consecutive Device IDs following the 79 + Device ID base 80 + maximum: 0x80000 81 + 82 + msi-map-mask: 83 + description: A mask to be applied to each Device ID prior to being 84 + mapped to an msi-specifier per the msi-map property. 85 + $ref: /schemas/types.yaml#/definitions/uint32 86 + maximum: 0x7ffff 55 87 56 88 num-lanes: 57 89 description: maximum number of lanes
+1
drivers/base/platform-msi.c
··· 95 95 void platform_device_msi_free_irqs_all(struct device *dev) 96 96 { 97 97 msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); 98 + msi_remove_device_irq_domain(dev, MSI_DEFAULT_DOMAIN); 98 99 } 99 100 EXPORT_SYMBOL_GPL(platform_device_msi_free_irqs_all);
+1 -1
drivers/irqchip/irq-bcm2712-mip.c
··· 11 11 #include <linux/of_address.h> 12 12 #include <linux/of_platform.h> 13 13 14 - #include "irq-msi-lib.h" 14 + #include <linux/irqchip/irq-msi-lib.h> 15 15 16 16 #define MIP_INT_RAISE 0x00 17 17 #define MIP_INT_CLEAR 0x10
+9 -9
drivers/irqchip/irq-gic-v2m.c
··· 26 26 #include <linux/irqchip/arm-gic.h> 27 27 #include <linux/irqchip/arm-gic-common.h> 28 28 29 - #include "irq-msi-lib.h" 29 + #include <linux/irqchip/irq-msi-lib.h> 30 30 31 31 /* 32 32 * MSI_TYPER: ··· 261 261 262 262 static __init int gicv2m_allocate_domains(struct irq_domain *parent) 263 263 { 264 - struct irq_domain *inner_domain; 264 + struct irq_domain_info info = { 265 + .ops = &gicv2m_domain_ops, 266 + .parent = parent, 267 + }; 265 268 struct v2m_data *v2m; 266 269 267 270 v2m = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry); 268 271 if (!v2m) 269 272 return 0; 270 273 271 - inner_domain = irq_domain_create_hierarchy(parent, 0, 0, v2m->fwnode, 272 - &gicv2m_domain_ops, v2m); 273 - if (!inner_domain) { 274 + info.host_data = v2m; 275 + info.fwnode = v2m->fwnode; 276 + 277 + if (!msi_create_parent_irq_domain(&info, &gicv2m_msi_parent_ops)) { 274 278 pr_err("Failed to create GICv2m domain\n"); 275 279 return -ENOMEM; 276 280 } 277 - 278 - irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); 279 - inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 280 - inner_domain->msi_parent_ops = &gicv2m_msi_parent_ops; 281 281 return 0; 282 282 } 283 283
+19 -20
drivers/irqchip/irq-gic-v3-its-msi-parent.c
··· 8 8 #include <linux/pci.h> 9 9 10 10 #include "irq-gic-common.h" 11 - #include "irq-msi-lib.h" 11 + #include <linux/irqchip/irq-msi-lib.h> 12 12 13 13 #define ITS_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 14 14 MSI_FLAG_USE_DEF_CHIP_OPS | \ ··· 68 68 info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain->parent, pdev); 69 69 70 70 /* 71 - * @domain->msi_domain_info->hwsize contains the size of the 72 - * MSI[-X] domain, but vector allocation happens one by one. This 73 - * needs some thought when MSI comes into play as the size of MSI 74 - * might be unknown at domain creation time and therefore set to 75 - * MSI_MAX_INDEX. 76 - */ 77 - msi_info = msi_get_domain_info(domain); 78 - if (msi_info->hwsize > nvec) 79 - nvec = msi_info->hwsize; 80 - 81 - /* 82 71 * Always allocate a power of 2, and special case device 0 for 83 72 * broken systems where the DevID is not wired (and all devices 84 73 * appear as DevID 0). For that reason, we generously allocate a ··· 107 118 index++; 108 119 } while (!ret); 109 120 121 + if (ret) { 122 + struct device_node *np = NULL; 123 + 124 + ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id); 125 + if (np) 126 + of_node_put(np); 127 + } 128 + 110 129 return ret; 111 130 } 112 131 ··· 140 143 /* ITS specific DeviceID, as the core ITS ignores dev. */ 141 144 info->scratchpad[0].ul = dev_id; 142 145 143 - /* 144 - * @domain->msi_domain_info->hwsize contains the size of the device 145 - * domain, but vector allocation happens one by one. 146 - */ 147 - msi_info = msi_get_domain_info(domain); 148 - if (msi_info->hwsize > nvec) 149 - nvec = msi_info->hwsize; 150 - 151 146 /* Allocate at least 32 MSIs, and always as a power of 2 */ 152 147 nvec = max_t(int, 32, roundup_pow_of_two(nvec)); 153 148 154 149 msi_info = msi_get_domain_info(domain->parent); 155 150 return msi_info->ops->msi_prepare(domain->parent, 156 151 dev, nvec, info); 152 + } 153 + 154 + static void its_msi_teardown(struct irq_domain *domain, msi_alloc_info_t *info) 155 + { 156 + struct msi_domain_info *msi_info; 157 + 158 + msi_info = msi_get_domain_info(domain->parent); 159 + msi_info->ops->msi_teardown(domain->parent, info); 157 160 } 158 161 159 162 static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain, ··· 179 182 * %MSI_MAX_INDEX. 180 183 */ 181 184 info->ops->msi_prepare = its_pci_msi_prepare; 185 + info->ops->msi_teardown = its_msi_teardown; 182 186 break; 183 187 case DOMAIN_BUS_DEVICE_MSI: 184 188 case DOMAIN_BUS_WIRED_TO_MSI: ··· 188 190 * size is also known at domain creation time. 189 191 */ 190 192 info->ops->msi_prepare = its_pmsi_prepare; 193 + info->ops->msi_teardown = its_msi_teardown; 191 194 break; 192 195 default: 193 196 /* Confused. How did the lib return true? */
+35 -35
drivers/irqchip/irq-gic-v3-its.c
··· 41 41 #include <asm/exception.h> 42 42 43 43 #include "irq-gic-common.h" 44 - #include "irq-msi-lib.h" 44 + #include <linux/irqchip/irq-msi-lib.h> 45 45 46 46 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) 47 47 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) ··· 3624 3624 return err; 3625 3625 } 3626 3626 3627 + static void its_msi_teardown(struct irq_domain *domain, msi_alloc_info_t *info) 3628 + { 3629 + struct its_device *its_dev = info->scratchpad[0].ptr; 3630 + 3631 + guard(mutex)(&its_dev->its->dev_alloc_lock); 3632 + 3633 + /* If the device is shared, keep everything around */ 3634 + if (its_dev->shared) 3635 + return; 3636 + 3637 + /* LPIs should have been already unmapped at this stage */ 3638 + if (WARN_ON_ONCE(!bitmap_empty(its_dev->event_map.lpi_map, 3639 + its_dev->event_map.nr_lpis))) 3640 + return; 3641 + 3642 + its_lpi_free(its_dev->event_map.lpi_map, 3643 + its_dev->event_map.lpi_base, 3644 + its_dev->event_map.nr_lpis); 3645 + 3646 + /* Unmap device/itt, and get rid of the tracking */ 3647 + its_send_mapd(its_dev, 0); 3648 + its_free_device(its_dev); 3649 + } 3650 + 3627 3651 static struct msi_domain_ops its_msi_domain_ops = { 3628 3652 .msi_prepare = its_msi_prepare, 3653 + .msi_teardown = its_msi_teardown, 3629 3654 }; 3630 3655 3631 3656 static int its_irq_gic_domain_alloc(struct irq_domain *domain, ··· 3751 3726 { 3752 3727 struct irq_data *d = irq_domain_get_irq_data(domain, virq); 3753 3728 struct its_device *its_dev = irq_data_get_irq_chip_data(d); 3754 - struct its_node *its = its_dev->its; 3755 3729 int i; 3756 3730 3757 3731 bitmap_release_region(its_dev->event_map.lpi_map, ··· 3763 3739 /* Nuke the entry in the domain */ 3764 3740 irq_domain_reset_irq_data(data); 3765 3741 } 3766 - 3767 - mutex_lock(&its->dev_alloc_lock); 3768 - 3769 - /* 3770 - * If all interrupts have been freed, start mopping the 3771 - * floor. This is conditioned on the device not being shared. 3772 - */ 3773 - if (!its_dev->shared && 3774 - bitmap_empty(its_dev->event_map.lpi_map, 3775 - its_dev->event_map.nr_lpis)) { 3776 - its_lpi_free(its_dev->event_map.lpi_map, 3777 - its_dev->event_map.lpi_base, 3778 - its_dev->event_map.nr_lpis); 3779 - 3780 - /* Unmap device/itt */ 3781 - its_send_mapd(its_dev, 0); 3782 - its_free_device(its_dev); 3783 - } 3784 - 3785 - mutex_unlock(&its->dev_alloc_lock); 3786 3742 3787 3743 irq_domain_free_irqs_parent(domain, virq, nr_irqs); 3788 3744 } ··· 5126 5122 5127 5123 static int its_init_domain(struct its_node *its) 5128 5124 { 5129 - struct irq_domain *inner_domain; 5125 + struct irq_domain_info dom_info = { 5126 + .fwnode = its->fwnode_handle, 5127 + .ops = &its_domain_ops, 5128 + .domain_flags = its->msi_domain_flags, 5129 + .parent = its_parent, 5130 + }; 5130 5131 struct msi_domain_info *info; 5131 5132 5132 5133 info = kzalloc(sizeof(*info), GFP_KERNEL); ··· 5140 5131 5141 5132 info->ops = &its_msi_domain_ops; 5142 5133 info->data = its; 5134 + dom_info.host_data = info; 5143 5135 5144 - inner_domain = irq_domain_create_hierarchy(its_parent, 5145 - its->msi_domain_flags, 0, 5146 - its->fwnode_handle, &its_domain_ops, 5147 - info); 5148 - if (!inner_domain) { 5136 + if (!msi_create_parent_irq_domain(&dom_info, &gic_v3_its_msi_parent_ops)) { 5149 5137 kfree(info); 5150 5138 return -ENOMEM; 5151 5139 } 5152 - 5153 - irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); 5154 - 5155 - inner_domain->msi_parent_ops = &gic_v3_its_msi_parent_ops; 5156 - inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 5157 - 5158 5140 return 0; 5159 5141 } 5160 5142 ··· 5522 5522 its->base = its_base; 5523 5523 its->phys_base = res->start; 5524 5524 its->get_msi_base = its_irq_get_msi_base; 5525 - its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI; 5525 + its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI | IRQ_DOMAIN_FLAG_MSI_IMMUTABLE; 5526 5526 5527 5527 its->numa_node = numa_node; 5528 5528 its->fwnode_handle = handle;
+7 -11
drivers/irqchip/irq-gic-v3-mbi.c
··· 18 18 19 19 #include <linux/irqchip/arm-gic-v3.h> 20 20 21 - #include "irq-msi-lib.h" 21 + #include <linux/irqchip/irq-msi-lib.h> 22 22 23 23 struct mbi_range { 24 24 u32 spi_start; ··· 206 206 207 207 static int mbi_allocate_domain(struct irq_domain *parent) 208 208 { 209 - struct irq_domain *nexus_domain; 209 + struct irq_domain_info info = { 210 + .fwnode = parent->fwnode, 211 + .ops = &mbi_domain_ops, 212 + .parent = parent, 213 + }; 210 214 211 - nexus_domain = irq_domain_create_hierarchy(parent, 0, 0, parent->fwnode, 212 - &mbi_domain_ops, NULL); 213 - if (!nexus_domain) 214 - return -ENOMEM; 215 - 216 - irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS); 217 - nexus_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 218 - nexus_domain->msi_parent_ops = &gic_v3_mbi_msi_parent_ops; 219 - return 0; 215 + return msi_create_parent_irq_domain(&info, &gic_v3_mbi_msi_parent_ops) ? 0 : -ENOMEM; 220 216 } 221 217 222 218 int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
+1 -1
drivers/irqchip/irq-imx-mu-msi.c
··· 24 24 #include <linux/pm_domain.h> 25 25 #include <linux/spinlock.h> 26 26 27 - #include "irq-msi-lib.h" 27 + #include <linux/irqchip/irq-msi-lib.h> 28 28 29 29 #define IMX_MU_CHANS 4 30 30
+1 -1
drivers/irqchip/irq-loongarch-avec.c
··· 18 18 #include <asm/loongarch.h> 19 19 #include <asm/setup.h> 20 20 21 - #include "irq-msi-lib.h" 21 + #include <linux/irqchip/irq-msi-lib.h> 22 22 #include "irq-loongson.h" 23 23 24 24 #define VECTORS_PER_REG 64
+1 -1
drivers/irqchip/irq-loongson-pch-msi.c
··· 15 15 #include <linux/pci.h> 16 16 #include <linux/slab.h> 17 17 18 - #include "irq-msi-lib.h" 18 + #include <linux/irqchip/irq-msi-lib.h> 19 19 #include "irq-loongson.h" 20 20 21 21 static int nr_pics;
+7 -2
drivers/irqchip/irq-msi-lib.c
··· 4 4 5 5 #include <linux/export.h> 6 6 7 - #include "irq-msi-lib.h" 7 + #include <linux/irqchip/irq-msi-lib.h> 8 8 9 9 /** 10 10 * msi_lib_init_dev_msi_info - Domain info setup for MSI domains ··· 105 105 * MSI message into the hardware which is the whole purpose of the 106 106 * device MSI domain aside of mask/unmask which is provided e.g. by 107 107 * PCI/MSI device domains. 108 + * 109 + * The exception to the rule is when the underlying domain 110 + * tells you that affinity is not a thing -- for example when 111 + * everything is muxed behind a single interrupt. 108 112 */ 109 - chip->irq_set_affinity = msi_domain_set_affinity; 113 + if (!chip->irq_set_affinity && !(info->flags & MSI_FLAG_NO_AFFINITY)) 114 + chip->irq_set_affinity = msi_domain_set_affinity; 110 115 return true; 111 116 } 112 117 EXPORT_SYMBOL_GPL(msi_lib_init_dev_msi_info);
+3 -3
drivers/irqchip/irq-msi-lib.h include/linux/irqchip/irq-msi-lib.h
··· 2 2 // Copyright (C) 2022 Linutronix GmbH 3 3 // Copyright (C) 2022 Intel 4 4 5 - #ifndef _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H 6 - #define _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H 5 + #ifndef _IRQCHIP_IRQ_MSI_LIB_H 6 + #define _IRQCHIP_IRQ_MSI_LIB_H 7 7 8 8 #include <linux/bits.h> 9 9 #include <linux/irqdomain.h> ··· 24 24 struct irq_domain *real_parent, 25 25 struct msi_domain_info *info); 26 26 27 - #endif /* _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H */ 27 + #endif /* _IRQCHIP_IRQ_MSI_LIB_H */
+11 -15
drivers/irqchip/irq-mvebu-gicp.c
··· 17 17 #include <linux/of_platform.h> 18 18 #include <linux/platform_device.h> 19 19 20 - #include "irq-msi-lib.h" 20 + #include <linux/irqchip/irq-msi-lib.h> 21 21 22 22 #include <dt-bindings/interrupt-controller/arm-gic.h> 23 23 ··· 170 170 171 171 static int mvebu_gicp_probe(struct platform_device *pdev) 172 172 { 173 - struct irq_domain *inner_domain, *parent_domain; 174 173 struct device_node *node = pdev->dev.of_node; 175 174 struct device_node *irq_parent_dn; 175 + struct irq_domain_info info = { 176 + .fwnode = of_fwnode_handle(node), 177 + .ops = &gicp_domain_ops, 178 + }; 176 179 struct mvebu_gicp *gicp; 177 180 int ret, i; 178 181 ··· 220 217 if (!gicp->spi_bitmap) 221 218 return -ENOMEM; 222 219 220 + info.size = gicp->spi_cnt; 221 + info.host_data = gicp; 222 + 223 223 irq_parent_dn = of_irq_find_parent(node); 224 224 if (!irq_parent_dn) { 225 225 dev_err(&pdev->dev, "failed to find parent IRQ node\n"); 226 226 return -ENODEV; 227 227 } 228 228 229 - parent_domain = irq_find_host(irq_parent_dn); 229 + info.parent = irq_find_host(irq_parent_dn); 230 230 of_node_put(irq_parent_dn); 231 - if (!parent_domain) { 231 + if (!info.parent) { 232 232 dev_err(&pdev->dev, "failed to find parent IRQ domain\n"); 233 233 return -ENODEV; 234 234 } 235 235 236 - inner_domain = irq_domain_create_hierarchy(parent_domain, 0, 237 - gicp->spi_cnt, 238 - of_node_to_fwnode(node), 239 - &gicp_domain_ops, gicp); 240 - if (!inner_domain) 241 - return -ENOMEM; 242 - 243 - irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI); 244 - inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 245 - inner_domain->msi_parent_ops = &gicp_msi_parent_ops; 246 - return 0; 236 + return msi_create_parent_irq_domain(&info, &gicp_msi_parent_ops) ? 0 : -ENOMEM; 247 237 } 248 238 249 239 static const struct of_device_id mvebu_gicp_of_match[] = {
+1 -1
drivers/irqchip/irq-mvebu-icu.c
··· 20 20 #include <linux/of_platform.h> 21 21 #include <linux/platform_device.h> 22 22 23 - #include "irq-msi-lib.h" 23 + #include <linux/irqchip/irq-msi-lib.h> 24 24 25 25 #include <dt-bindings/interrupt-controller/mvebu-icu.h> 26 26
+10 -17
drivers/irqchip/irq-mvebu-odmi.c
··· 18 18 #include <linux/of_address.h> 19 19 #include <linux/slab.h> 20 20 21 - #include "irq-msi-lib.h" 21 + #include <linux/irqchip/irq-msi-lib.h> 22 22 23 23 #include <dt-bindings/interrupt-controller/arm-gic.h> 24 24 ··· 167 167 static int __init mvebu_odmi_init(struct device_node *node, 168 168 struct device_node *parent) 169 169 { 170 - struct irq_domain *parent_domain, *inner_domain; 170 + struct irq_domain_info info = { 171 + .fwnode = of_fwnode_handle(node), 172 + .ops = &odmi_domain_ops, 173 + .size = odmis_count * NODMIS_PER_FRAME, 174 + .parent = irq_find_host(parent), 175 + }; 171 176 int ret, i; 172 177 173 178 if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count)) ··· 208 203 } 209 204 } 210 205 211 - parent_domain = irq_find_host(parent); 206 + if (msi_create_parent_irq_domain(&info, &odmi_msi_parent_ops)) 207 + return 0; 212 208 213 - inner_domain = irq_domain_create_hierarchy(parent_domain, 0, 214 - odmis_count * NODMIS_PER_FRAME, 215 - of_node_to_fwnode(node), 216 - &odmi_domain_ops, NULL); 217 - if (!inner_domain) { 218 - ret = -ENOMEM; 219 - goto err_unmap; 220 - } 221 - 222 - irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI); 223 - inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 224 - inner_domain->msi_parent_ops = &odmi_msi_parent_ops; 225 - 226 - return 0; 209 + ret = -ENOMEM; 227 210 228 211 err_unmap: 229 212 for (i = 0; i < odmis_count; i++) {
+12 -12
drivers/irqchip/irq-mvebu-sei.c
··· 14 14 #include <linux/of_irq.h> 15 15 #include <linux/of_platform.h> 16 16 17 - #include "irq-msi-lib.h" 17 + #include <linux/irqchip/irq-msi-lib.h> 18 18 19 19 /* Cause register */ 20 20 #define GICP_SECR(idx) (0x0 + ((idx) * 0x4)) ··· 366 366 static int mvebu_sei_probe(struct platform_device *pdev) 367 367 { 368 368 struct device_node *node = pdev->dev.of_node; 369 + struct irq_domain_info info = { 370 + .fwnode = of_fwnode_handle(node), 371 + .ops = &mvebu_sei_cp_domain_ops, 372 + }; 369 373 struct mvebu_sei *sei; 370 374 u32 parent_irq; 371 375 int ret; ··· 406 402 } 407 403 408 404 /* Create the root SEI domain */ 409 - sei->sei_domain = irq_domain_create_linear(of_node_to_fwnode(node), 405 + sei->sei_domain = irq_domain_create_linear(of_fwnode_handle(node), 410 406 (sei->caps->ap_range.size + 411 407 sei->caps->cp_range.size), 412 408 &mvebu_sei_domain_ops, ··· 422 418 /* Create the 'wired' domain */ 423 419 sei->ap_domain = irq_domain_create_hierarchy(sei->sei_domain, 0, 424 420 sei->caps->ap_range.size, 425 - of_node_to_fwnode(node), 421 + of_fwnode_handle(node), 426 422 &mvebu_sei_ap_domain_ops, 427 423 sei); 428 424 if (!sei->ap_domain) { ··· 434 430 irq_domain_update_bus_token(sei->ap_domain, DOMAIN_BUS_WIRED); 435 431 436 432 /* Create the 'MSI' domain */ 437 - sei->cp_domain = irq_domain_create_hierarchy(sei->sei_domain, 0, 438 - sei->caps->cp_range.size, 439 - of_node_to_fwnode(node), 440 - &mvebu_sei_cp_domain_ops, 441 - sei); 433 + info.size = sei->caps->cp_range.size; 434 + info.host_data = sei; 435 + info.parent = sei->sei_domain; 436 + 437 + sei->cp_domain = msi_create_parent_irq_domain(&info, &sei_msi_parent_ops); 442 438 if (!sei->cp_domain) { 443 439 pr_err("Failed to create CPs IRQ domain\n"); 444 440 ret = -ENOMEM; 445 441 goto remove_ap_domain; 446 442 } 447 - 448 - irq_domain_update_bus_token(sei->cp_domain, DOMAIN_BUS_GENERIC_MSI); 449 - sei->cp_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 450 - sei->cp_domain->msi_parent_ops = &sei_msi_parent_ops; 451 443 452 444 mvebu_sei_reset(sei); 453 445
+1 -1
drivers/irqchip/irq-riscv-imsic-platform.c
··· 20 20 #include <linux/spinlock.h> 21 21 #include <linux/smp.h> 22 22 23 - #include "irq-msi-lib.h" 23 + #include <linux/irqchip/irq-msi-lib.h> 24 24 #include "irq-riscv-imsic-state.h" 25 25 26 26 static bool imsic_cpu_page_phys(unsigned int cpu, unsigned int guest_index,
+1 -1
drivers/irqchip/irq-sg2042-msi.c
··· 17 17 #include <linux/property.h> 18 18 #include <linux/slab.h> 19 19 20 - #include "irq-msi-lib.h" 20 + #include <linux/irqchip/irq-msi-lib.h> 21 21 22 22 struct sg204x_msi_chip_info { 23 23 const struct irq_chip *irqchip;
+8 -14
drivers/ntb/msi.c
··· 106 106 if (!ntb->msi) 107 107 return -EINVAL; 108 108 109 - msi_lock_descs(&ntb->pdev->dev); 110 - desc = msi_first_desc(&ntb->pdev->dev, MSI_DESC_ASSOCIATED); 111 - addr = desc->msg.address_lo + ((uint64_t)desc->msg.address_hi << 32); 112 - msi_unlock_descs(&ntb->pdev->dev); 109 + scoped_guard (msi_descs_lock, &ntb->pdev->dev) { 110 + desc = msi_first_desc(&ntb->pdev->dev, MSI_DESC_ASSOCIATED); 111 + addr = desc->msg.address_lo + ((uint64_t)desc->msg.address_hi << 32); 112 + } 113 113 114 114 for (peer = 0; peer < ntb_peer_port_count(ntb); peer++) { 115 115 peer_widx = ntb_peer_highest_mw_idx(ntb, peer); ··· 289 289 if (!ntb->msi) 290 290 return -EINVAL; 291 291 292 - msi_lock_descs(dev); 292 + guard(msi_descs_lock)(dev); 293 293 msi_for_each_desc(entry, dev, MSI_DESC_ASSOCIATED) { 294 294 if (irq_has_action(entry->irq)) 295 295 continue; ··· 307 307 ret = ntbm_msi_setup_callback(ntb, entry, msi_desc); 308 308 if (ret) { 309 309 devm_free_irq(&ntb->dev, entry->irq, dev_id); 310 - goto unlock; 310 + return ret; 311 311 } 312 - 313 - ret = entry->irq; 314 - goto unlock; 312 + return entry->irq; 315 313 } 316 - ret = -ENODEV; 317 - 318 - unlock: 319 - msi_unlock_descs(dev); 320 - return ret; 314 + return -ENODEV; 321 315 } 322 316 EXPORT_SYMBOL(ntbm_msi_request_threaded_irq); 323 317
+3
drivers/pci/controller/Kconfig
··· 40 40 depends on OF 41 41 depends on PCI_MSI 42 42 select PCI_HOST_COMMON 43 + select IRQ_MSI_LIB 43 44 help 44 45 Say Y here if you want to enable PCIe controller support on Apple 45 46 system-on-chips, like the Apple M1. This is required for the USB ··· 228 227 bool "NVIDIA Tegra PCIe controller" 229 228 depends on ARCH_TEGRA || COMPILE_TEST 230 229 depends on PCI_MSI 230 + select IRQ_MSI_LIB 231 231 help 232 232 Say Y here if you want support for the PCIe host controller found 233 233 on NVIDIA Tegra SoCs. ··· 305 303 bool "X-Gene v1 PCIe MSI feature" 306 304 depends on PCI_XGENE 307 305 depends on PCI_MSI 306 + select IRQ_MSI_LIB 308 307 default y 309 308 help 310 309 Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC.
+4 -10
drivers/pci/controller/pci-hyperv.c
··· 3975 3975 { 3976 3976 struct irq_data *irq_data; 3977 3977 struct msi_desc *entry; 3978 - int ret = 0; 3979 3978 3980 3979 if (!pdev->msi_enabled && !pdev->msix_enabled) 3981 3980 return 0; 3982 3981 3983 - msi_lock_descs(&pdev->dev); 3982 + guard(msi_descs_lock)(&pdev->dev); 3984 3983 msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) { 3985 3984 irq_data = irq_get_irq_data(entry->irq); 3986 - if (WARN_ON_ONCE(!irq_data)) { 3987 - ret = -EINVAL; 3988 - break; 3989 - } 3990 - 3985 + if (WARN_ON_ONCE(!irq_data)) 3986 + return -EINVAL; 3991 3987 hv_compose_msi_msg(irq_data, &entry->msg); 3992 3988 } 3993 - msi_unlock_descs(&pdev->dev); 3994 - 3995 - return ret; 3989 + return 0; 3996 3990 } 3997 3991 3998 3992 /*
+19 -44
drivers/pci/controller/pci-tegra.c
··· 22 22 #include <linux/iopoll.h> 23 23 #include <linux/irq.h> 24 24 #include <linux/irqchip/chained_irq.h> 25 + #include <linux/irqchip/irq-msi-lib.h> 25 26 #include <linux/irqdomain.h> 26 27 #include <linux/kernel.h> 27 28 #include <linux/init.h> ··· 1548 1547 unsigned int index = i * 32 + offset; 1549 1548 int ret; 1550 1549 1551 - ret = generic_handle_domain_irq(msi->domain->parent, index); 1550 + ret = generic_handle_domain_irq(msi->domain, index); 1552 1551 if (ret) { 1553 1552 /* 1554 1553 * that's weird who triggered this? ··· 1565 1564 1566 1565 chained_irq_exit(chip, desc); 1567 1566 } 1568 - 1569 - static void tegra_msi_top_irq_ack(struct irq_data *d) 1570 - { 1571 - irq_chip_ack_parent(d); 1572 - } 1573 - 1574 - static void tegra_msi_top_irq_mask(struct irq_data *d) 1575 - { 1576 - pci_msi_mask_irq(d); 1577 - irq_chip_mask_parent(d); 1578 - } 1579 - 1580 - static void tegra_msi_top_irq_unmask(struct irq_data *d) 1581 - { 1582 - pci_msi_unmask_irq(d); 1583 - irq_chip_unmask_parent(d); 1584 - } 1585 - 1586 - static struct irq_chip tegra_msi_top_chip = { 1587 - .name = "Tegra PCIe MSI", 1588 - .irq_ack = tegra_msi_top_irq_ack, 1589 - .irq_mask = tegra_msi_top_irq_mask, 1590 - .irq_unmask = tegra_msi_top_irq_unmask, 1591 - }; 1592 1567 1593 1568 static void tegra_msi_irq_ack(struct irq_data *d) 1594 1569 { ··· 1667 1690 .free = tegra_msi_domain_free, 1668 1691 }; 1669 1692 1670 - static struct msi_domain_info tegra_msi_info = { 1671 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 1672 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 1673 - .chip = &tegra_msi_top_chip, 1693 + static const struct msi_parent_ops tegra_msi_parent_ops = { 1694 + .supported_flags = (MSI_GENERIC_FLAGS_MASK | 1695 + MSI_FLAG_PCI_MSIX), 1696 + .required_flags = (MSI_FLAG_USE_DEF_DOM_OPS | 1697 + MSI_FLAG_USE_DEF_CHIP_OPS | 1698 + MSI_FLAG_PCI_MSI_MASK_PARENT | 1699 + MSI_FLAG_NO_AFFINITY), 1700 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 1701 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 1702 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 1674 1703 }; 1675 1704 1676 1705 static int tegra_allocate_domains(struct tegra_msi *msi) 1677 1706 { 1678 1707 struct tegra_pcie *pcie = msi_to_pcie(msi); 1679 1708 struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); 1680 - struct irq_domain *parent; 1709 + struct irq_domain_info info = { 1710 + .fwnode = fwnode, 1711 + .ops = &tegra_msi_domain_ops, 1712 + .size = INT_PCI_MSI_NR, 1713 + .host_data = msi, 1714 + }; 1681 1715 1682 - parent = irq_domain_create_linear(fwnode, INT_PCI_MSI_NR, 1683 - &tegra_msi_domain_ops, msi); 1684 - if (!parent) { 1685 - dev_err(pcie->dev, "failed to create IRQ domain\n"); 1686 - return -ENOMEM; 1687 - } 1688 - irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 1689 - 1690 - msi->domain = pci_msi_create_irq_domain(fwnode, &tegra_msi_info, parent); 1716 + msi->domain = msi_create_parent_irq_domain(&info, &tegra_msi_parent_ops); 1691 1717 if (!msi->domain) { 1692 1718 dev_err(pcie->dev, "failed to create MSI domain\n"); 1693 - irq_domain_remove(parent); 1694 1719 return -ENOMEM; 1695 1720 } 1696 - 1697 1721 return 0; 1698 1722 } 1699 1723 1700 1724 static void tegra_free_domains(struct tegra_msi *msi) 1701 1725 { 1702 - struct irq_domain *parent = msi->domain->parent; 1703 - 1704 1726 irq_domain_remove(msi->domain); 1705 - irq_domain_remove(parent); 1706 1727 } 1707 1728 1708 1729 static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
+19 -32
drivers/pci/controller/pci-xgene-msi.c
··· 12 12 #include <linux/module.h> 13 13 #include <linux/msi.h> 14 14 #include <linux/irqchip/chained_irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/pci.h> 16 17 #include <linux/platform_device.h> 17 18 #include <linux/of_pci.h> ··· 33 32 struct xgene_msi { 34 33 struct device_node *node; 35 34 struct irq_domain *inner_domain; 36 - struct irq_domain *msi_domain; 37 35 u64 msi_addr; 38 36 void __iomem *msi_regs; 39 37 unsigned long *bitmap; ··· 43 43 44 44 /* Global data */ 45 45 static struct xgene_msi xgene_msi_ctrl; 46 - 47 - static struct irq_chip xgene_msi_top_irq_chip = { 48 - .name = "X-Gene1 MSI", 49 - .irq_enable = pci_msi_unmask_irq, 50 - .irq_disable = pci_msi_mask_irq, 51 - .irq_mask = pci_msi_mask_irq, 52 - .irq_unmask = pci_msi_unmask_irq, 53 - }; 54 - 55 - static struct msi_domain_info xgene_msi_domain_info = { 56 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 57 - MSI_FLAG_PCI_MSIX), 58 - .chip = &xgene_msi_top_irq_chip, 59 - }; 60 46 61 47 /* 62 48 * X-Gene v1 has 16 groups of MSI termination registers MSInIRx, where ··· 221 235 irq_domain_free_irqs_parent(domain, virq, nr_irqs); 222 236 } 223 237 224 - static const struct irq_domain_ops msi_domain_ops = { 238 + static const struct irq_domain_ops xgene_msi_domain_ops = { 225 239 .alloc = xgene_irq_domain_alloc, 226 240 .free = xgene_irq_domain_free, 227 241 }; 228 242 243 + static const struct msi_parent_ops xgene_msi_parent_ops = { 244 + .supported_flags = (MSI_GENERIC_FLAGS_MASK | 245 + MSI_FLAG_PCI_MSIX), 246 + .required_flags = (MSI_FLAG_USE_DEF_DOM_OPS | 247 + MSI_FLAG_USE_DEF_CHIP_OPS), 248 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 249 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 250 + }; 251 + 229 252 static int xgene_allocate_domains(struct xgene_msi *msi) 230 253 { 231 - msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC, 232 - &msi_domain_ops, msi); 233 - if (!msi->inner_domain) 234 - return -ENOMEM; 254 + struct irq_domain_info info = { 255 + .fwnode = of_fwnode_handle(msi->node), 256 + .ops = &xgene_msi_domain_ops, 257 + .size = NR_MSI_VEC, 258 + .host_data = msi, 259 + }; 235 260 236 - msi->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(msi->node), 237 - &xgene_msi_domain_info, 238 - msi->inner_domain); 239 - 240 - if (!msi->msi_domain) { 241 - irq_domain_remove(msi->inner_domain); 242 - return -ENOMEM; 243 - } 244 - 245 - return 0; 261 + msi->inner_domain = msi_create_parent_irq_domain(&info, &xgene_msi_parent_ops); 262 + return msi->inner_domain ? 0 : -ENOMEM; 246 263 } 247 264 248 265 static void xgene_free_domains(struct xgene_msi *msi) 249 266 { 250 - if (msi->msi_domain) 251 - irq_domain_remove(msi->msi_domain); 252 267 if (msi->inner_domain) 253 268 irq_domain_remove(msi->inner_domain); 254 269 }
+23 -46
drivers/pci/controller/pcie-apple.c
··· 22 22 #include <linux/kernel.h> 23 23 #include <linux/iopoll.h> 24 24 #include <linux/irqchip/chained_irq.h> 25 + #include <linux/irqchip/irq-msi-lib.h> 25 26 #include <linux/irqdomain.h> 26 27 #include <linux/list.h> 27 28 #include <linux/module.h> ··· 134 133 struct mutex lock; 135 134 struct device *dev; 136 135 void __iomem *base; 137 - struct irq_domain *domain; 138 136 unsigned long *bitmap; 139 137 struct list_head ports; 140 138 struct completion event; ··· 161 161 { 162 162 writel_relaxed(readl_relaxed(addr) & ~clr, addr); 163 163 } 164 - 165 - static void apple_msi_top_irq_mask(struct irq_data *d) 166 - { 167 - pci_msi_mask_irq(d); 168 - irq_chip_mask_parent(d); 169 - } 170 - 171 - static void apple_msi_top_irq_unmask(struct irq_data *d) 172 - { 173 - pci_msi_unmask_irq(d); 174 - irq_chip_unmask_parent(d); 175 - } 176 - 177 - static struct irq_chip apple_msi_top_chip = { 178 - .name = "PCIe MSI", 179 - .irq_mask = apple_msi_top_irq_mask, 180 - .irq_unmask = apple_msi_top_irq_unmask, 181 - .irq_eoi = irq_chip_eoi_parent, 182 - .irq_set_affinity = irq_chip_set_affinity_parent, 183 - .irq_set_type = irq_chip_set_type_parent, 184 - }; 185 164 186 165 static void apple_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) 187 166 { ··· 205 226 206 227 for (i = 0; i < nr_irqs; i++) { 207 228 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, 208 - &apple_msi_bottom_chip, 209 - domain->host_data); 229 + &apple_msi_bottom_chip, pcie); 210 230 } 211 231 212 232 return 0; ··· 227 249 static const struct irq_domain_ops apple_msi_domain_ops = { 228 250 .alloc = apple_msi_domain_alloc, 229 251 .free = apple_msi_domain_free, 230 - }; 231 - 232 - static struct msi_domain_info apple_msi_info = { 233 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 234 - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), 235 - .chip = &apple_msi_top_chip, 236 252 }; 237 253 238 254 static void apple_port_irq_mask(struct irq_data *data) ··· 567 595 return 0; 568 596 } 569 597 598 + static const struct msi_parent_ops apple_msi_parent_ops = { 599 + .supported_flags = (MSI_GENERIC_FLAGS_MASK | 600 + MSI_FLAG_PCI_MSIX | 601 + MSI_FLAG_MULTI_PCI_MSI), 602 + .required_flags = (MSI_FLAG_USE_DEF_DOM_OPS | 603 + MSI_FLAG_USE_DEF_CHIP_OPS | 604 + MSI_FLAG_PCI_MSI_MASK_PARENT), 605 + .chip_flags = MSI_CHIP_FLAG_SET_EOI, 606 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 607 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 608 + }; 609 + 570 610 static int apple_msi_init(struct apple_pcie *pcie) 571 611 { 572 612 struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); 613 + struct irq_domain_info info = { 614 + .fwnode = fwnode, 615 + .ops = &apple_msi_domain_ops, 616 + .size = pcie->nvecs, 617 + .host_data = pcie, 618 + }; 573 619 struct of_phandle_args args = {}; 574 - struct irq_domain *parent; 575 620 int ret; 576 621 577 622 ret = of_parse_phandle_with_args(to_of_node(fwnode), "msi-ranges", ··· 608 619 if (!pcie->bitmap) 609 620 return -ENOMEM; 610 621 611 - parent = irq_find_matching_fwspec(&pcie->fwspec, DOMAIN_BUS_WIRED); 612 - if (!parent) { 622 + info.parent = irq_find_matching_fwspec(&pcie->fwspec, DOMAIN_BUS_WIRED); 623 + if (!info.parent) { 613 624 dev_err(pcie->dev, "failed to find parent domain\n"); 614 625 return -ENXIO; 615 626 } 616 627 617 - parent = irq_domain_create_hierarchy(parent, 0, pcie->nvecs, fwnode, 618 - &apple_msi_domain_ops, pcie); 619 - if (!parent) { 628 + if (!msi_create_parent_irq_domain(&info, &apple_msi_parent_ops)) { 620 629 dev_err(pcie->dev, "failed to create IRQ domain\n"); 621 630 return -ENOMEM; 622 631 } 623 - irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 624 - 625 - pcie->domain = pci_msi_create_irq_domain(fwnode, &apple_msi_info, 626 - parent); 627 - if (!pcie->domain) { 628 - dev_err(pcie->dev, "failed to create MSI domain\n"); 629 - irq_domain_remove(parent); 630 - return -ENOMEM; 631 - } 632 - 633 632 return 0; 634 633 } 635 634
+3 -5
drivers/pci/msi/api.c
··· 53 53 if (!pci_msi_enabled() || !dev || !dev->msi_enabled) 54 54 return; 55 55 56 - msi_lock_descs(&dev->dev); 56 + guard(msi_descs_lock)(&dev->dev); 57 57 pci_msi_shutdown(dev); 58 58 pci_free_msi_irqs(dev); 59 - msi_unlock_descs(&dev->dev); 60 59 } 61 60 EXPORT_SYMBOL(pci_disable_msi); 62 61 ··· 195 196 if (!pci_msi_enabled() || !dev || !dev->msix_enabled) 196 197 return; 197 198 198 - msi_lock_descs(&dev->dev); 199 + guard(msi_descs_lock)(&dev->dev); 199 200 pci_msix_shutdown(dev); 200 201 pci_free_msi_irqs(dev); 201 - msi_unlock_descs(&dev->dev); 202 202 } 203 203 EXPORT_SYMBOL(pci_disable_msix); 204 204 ··· 399 401 * Return: true if MSI has not been globally disabled through ACPI FADT, 400 402 * PCI bridge quirks, or the "pci=nomsi" kernel command-line option. 401 403 */ 402 - int pci_msi_enabled(void) 404 + bool pci_msi_enabled(void) 403 405 { 404 406 return pci_msi_enable; 405 407 }
+112 -67
drivers/pci/msi/msi.c
··· 15 15 #include "../pci.h" 16 16 #include "msi.h" 17 17 18 - int pci_msi_enable = 1; 18 + bool pci_msi_enable = true; 19 19 20 20 /** 21 21 * pci_msi_supported - check whether MSI may be enabled on a device ··· 335 335 return !entry ? 0 : -EIO; 336 336 } 337 337 338 - /** 339 - * msi_capability_init - configure device's MSI capability structure 340 - * @dev: pointer to the pci_dev data structure of MSI device function 341 - * @nvec: number of interrupts to allocate 342 - * @affd: description of automatic IRQ affinity assignments (may be %NULL) 343 - * 344 - * Setup the MSI capability structure of the device with the requested 345 - * number of interrupts. A return value of zero indicates the successful 346 - * setup of an entry with the new MSI IRQ. A negative return value indicates 347 - * an error, and a positive return value indicates the number of interrupts 348 - * which could have been allocated. 349 - */ 350 - static int msi_capability_init(struct pci_dev *dev, int nvec, 351 - struct irq_affinity *affd) 338 + static int __msi_capability_init(struct pci_dev *dev, int nvec, struct irq_affinity_desc *masks) 352 339 { 353 - struct irq_affinity_desc *masks = NULL; 340 + int ret = msi_setup_msi_desc(dev, nvec, masks); 354 341 struct msi_desc *entry, desc; 355 - int ret; 356 342 357 - /* Reject multi-MSI early on irq domain enabled architectures */ 358 - if (nvec > 1 && !pci_msi_domain_supports(dev, MSI_FLAG_MULTI_PCI_MSI, ALLOW_LEGACY)) 359 - return 1; 360 - 361 - /* 362 - * Disable MSI during setup in the hardware, but mark it enabled 363 - * so that setup code can evaluate it. 364 - */ 365 - pci_msi_set_enable(dev, 0); 366 - dev->msi_enabled = 1; 367 - 368 - if (affd) 369 - masks = irq_create_affinity_masks(nvec, affd); 370 - 371 - msi_lock_descs(&dev->dev); 372 - ret = msi_setup_msi_desc(dev, nvec, masks); 373 343 if (ret) 374 - goto fail; 344 + return ret; 375 345 376 346 /* All MSIs are unmasked by default; mask them all */ 377 347 entry = msi_first_desc(&dev->dev, MSI_DESC_ALL); ··· 363 393 goto err; 364 394 365 395 /* Set MSI enabled bits */ 396 + dev->msi_enabled = 1; 366 397 pci_intx_for_msi(dev, 0); 367 398 pci_msi_set_enable(dev, 1); 368 399 369 400 pcibios_free_irq(dev); 370 401 dev->irq = entry->irq; 371 - goto unlock; 372 - 402 + return 0; 373 403 err: 374 404 pci_msi_unmask(&desc, msi_multi_mask(&desc)); 375 405 pci_free_msi_irqs(dev); 376 - fail: 377 - dev->msi_enabled = 0; 378 - unlock: 379 - msi_unlock_descs(&dev->dev); 380 - kfree(masks); 381 406 return ret; 407 + } 408 + 409 + /** 410 + * msi_capability_init - configure device's MSI capability structure 411 + * @dev: pointer to the pci_dev data structure of MSI device function 412 + * @nvec: number of interrupts to allocate 413 + * @affd: description of automatic IRQ affinity assignments (may be %NULL) 414 + * 415 + * Setup the MSI capability structure of the device with the requested 416 + * number of interrupts. A return value of zero indicates the successful 417 + * setup of an entry with the new MSI IRQ. A negative return value indicates 418 + * an error, and a positive return value indicates the number of interrupts 419 + * which could have been allocated. 420 + */ 421 + static int msi_capability_init(struct pci_dev *dev, int nvec, 422 + struct irq_affinity *affd) 423 + { 424 + /* Reject multi-MSI early on irq domain enabled architectures */ 425 + if (nvec > 1 && !pci_msi_domain_supports(dev, MSI_FLAG_MULTI_PCI_MSI, ALLOW_LEGACY)) 426 + return 1; 427 + 428 + /* 429 + * Disable MSI during setup in the hardware, but mark it enabled 430 + * so that setup code can evaluate it. 431 + */ 432 + pci_msi_set_enable(dev, 0); 433 + 434 + struct irq_affinity_desc *masks __free(kfree) = 435 + affd ? irq_create_affinity_masks(nvec, affd) : NULL; 436 + 437 + guard(msi_descs_lock)(&dev->dev); 438 + return __msi_capability_init(dev, nvec, masks); 382 439 } 383 440 384 441 int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, ··· 663 666 writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); 664 667 } 665 668 666 - static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 667 - int nvec, struct irq_affinity *affd) 669 + DEFINE_FREE(free_msi_irqs, struct pci_dev *, if (_T) pci_free_msi_irqs(_T)); 670 + 671 + static int __msix_setup_interrupts(struct pci_dev *__dev, struct msix_entry *entries, 672 + int nvec, struct irq_affinity_desc *masks) 668 673 { 669 - struct irq_affinity_desc *masks = NULL; 670 - int ret; 674 + struct pci_dev *dev __free(free_msi_irqs) = __dev; 671 675 672 - if (affd) 673 - masks = irq_create_affinity_masks(nvec, affd); 674 - 675 - msi_lock_descs(&dev->dev); 676 - ret = msix_setup_msi_descs(dev, entries, nvec, masks); 676 + int ret = msix_setup_msi_descs(dev, entries, nvec, masks); 677 677 if (ret) 678 - goto out_free; 678 + return ret; 679 679 680 680 ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 681 681 if (ret) 682 - goto out_free; 682 + return ret; 683 683 684 684 /* Check if all MSI entries honor device restrictions */ 685 685 ret = msi_verify_entries(dev); 686 686 if (ret) 687 - goto out_free; 687 + return ret; 688 688 689 689 msix_update_entries(dev, entries); 690 - goto out_unlock; 690 + retain_and_null_ptr(dev); 691 + return 0; 692 + } 691 693 692 - out_free: 693 - pci_free_msi_irqs(dev); 694 - out_unlock: 695 - msi_unlock_descs(&dev->dev); 696 - kfree(masks); 697 - return ret; 694 + static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 695 + int nvec, struct irq_affinity *affd) 696 + { 697 + struct irq_affinity_desc *masks __free(kfree) = 698 + affd ? irq_create_affinity_masks(nvec, affd) : NULL; 699 + 700 + guard(msi_descs_lock)(&dev->dev); 701 + return __msix_setup_interrupts(dev, entries, nvec, masks); 698 702 } 699 703 700 704 /** ··· 871 873 872 874 write_msg = arch_restore_msi_irqs(dev); 873 875 874 - msi_lock_descs(&dev->dev); 875 - msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 876 - if (write_msg) 877 - __pci_write_msi_msg(entry, &entry->msg); 878 - pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 876 + scoped_guard (msi_descs_lock, &dev->dev) { 877 + msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 878 + if (write_msg) 879 + __pci_write_msi_msg(entry, &entry->msg); 880 + pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 881 + } 879 882 } 880 - msi_unlock_descs(&dev->dev); 881 883 882 884 pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 883 885 } ··· 916 918 } 917 919 } 918 920 921 + #ifdef CONFIG_PCIE_TPH 922 + /** 923 + * pci_msix_write_tph_tag - Update the TPH tag for a given MSI-X vector 924 + * @pdev: The PCIe device to update 925 + * @index: The MSI-X index to update 926 + * @tag: The tag to write 927 + * 928 + * Returns: 0 on success, error code on failure 929 + */ 930 + int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag) 931 + { 932 + struct msi_desc *msi_desc; 933 + struct irq_desc *irq_desc; 934 + unsigned int virq; 935 + 936 + if (!pdev->msix_enabled) 937 + return -ENXIO; 938 + 939 + guard(msi_descs_lock)(&pdev->dev); 940 + virq = msi_get_virq(&pdev->dev, index); 941 + if (!virq) 942 + return -ENXIO; 943 + /* 944 + * This is a horrible hack, but short of implementing a PCI 945 + * specific interrupt chip callback and a huge pile of 946 + * infrastructure, this is the minor nuissance. It provides the 947 + * protection against concurrent operations on this entry and keeps 948 + * the control word cache in sync. 949 + */ 950 + irq_desc = irq_to_desc(virq); 951 + if (!irq_desc) 952 + return -ENXIO; 953 + 954 + guard(raw_spinlock_irq)(&irq_desc->lock); 955 + msi_desc = irq_data_get_msi_desc(&irq_desc->irq_data); 956 + if (!msi_desc || msi_desc->pci.msi_attrib.is_virtual) 957 + return -ENXIO; 958 + 959 + msi_desc->pci.msix_ctrl &= ~PCI_MSIX_ENTRY_CTRL_ST; 960 + msi_desc->pci.msix_ctrl |= FIELD_PREP(PCI_MSIX_ENTRY_CTRL_ST, tag); 961 + pci_msix_write_vector_ctrl(msi_desc, msi_desc->pci.msix_ctrl); 962 + /* Flush the write */ 963 + readl(pci_msix_desc_addr(msi_desc)); 964 + return 0; 965 + } 966 + #endif 967 + 919 968 /* Misc. infrastructure */ 920 969 921 970 struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc) ··· 973 928 974 929 void pci_no_msi(void) 975 930 { 976 - pci_msi_enable = 0; 931 + pci_msi_enable = false; 977 932 }
+1 -1
drivers/pci/msi/msi.h
··· 87 87 void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc); 88 88 89 89 /* Subsystem variables */ 90 - extern int pci_msi_enable; 90 + extern bool pci_msi_enable; 91 91 92 92 /* MSI internal functions invoked from the public APIs */ 93 93 void pci_msi_shutdown(struct pci_dev *dev);
+9
drivers/pci/pci.h
··· 1064 1064 const char *name); 1065 1065 void pcim_release_region(struct pci_dev *pdev, int bar); 1066 1066 1067 + #ifdef CONFIG_PCI_MSI 1068 + int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag); 1069 + #else 1070 + static inline int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag) 1071 + { 1072 + return -ENODEV; 1073 + } 1074 + #endif 1075 + 1067 1076 /* 1068 1077 * Config Address for PCI Configuration Mechanism #1 1069 1078 *
+1 -43
drivers/pci/tph.c
··· 204 204 return FIELD_GET(PCI_EXP_DEVCAP2_TPH_COMP_MASK, reg); 205 205 } 206 206 207 - /* Write ST to MSI-X vector control reg - Return 0 if OK, otherwise -errno */ 208 - static int write_tag_to_msix(struct pci_dev *pdev, int msix_idx, u16 tag) 209 - { 210 - #ifdef CONFIG_PCI_MSI 211 - struct msi_desc *msi_desc = NULL; 212 - void __iomem *vec_ctrl; 213 - u32 val; 214 - int err = 0; 215 - 216 - msi_lock_descs(&pdev->dev); 217 - 218 - /* Find the msi_desc entry with matching msix_idx */ 219 - msi_for_each_desc(msi_desc, &pdev->dev, MSI_DESC_ASSOCIATED) { 220 - if (msi_desc->msi_index == msix_idx) 221 - break; 222 - } 223 - 224 - if (!msi_desc) { 225 - err = -ENXIO; 226 - goto err_out; 227 - } 228 - 229 - /* Get the vector control register (offset 0xc) pointed by msix_idx */ 230 - vec_ctrl = pdev->msix_base + msix_idx * PCI_MSIX_ENTRY_SIZE; 231 - vec_ctrl += PCI_MSIX_ENTRY_VECTOR_CTRL; 232 - 233 - val = readl(vec_ctrl); 234 - val &= ~PCI_MSIX_ENTRY_CTRL_ST; 235 - val |= FIELD_PREP(PCI_MSIX_ENTRY_CTRL_ST, tag); 236 - writel(val, vec_ctrl); 237 - 238 - /* Read back to flush the update */ 239 - val = readl(vec_ctrl); 240 - 241 - err_out: 242 - msi_unlock_descs(&pdev->dev); 243 - return err; 244 - #else 245 - return -ENODEV; 246 - #endif 247 - } 248 - 249 207 /* Write tag to ST table - Return 0 if OK, otherwise -errno */ 250 208 static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag) 251 209 { ··· 304 346 305 347 switch (loc) { 306 348 case PCI_TPH_LOC_MSIX: 307 - err = write_tag_to_msix(pdev, index, tag); 349 + err = pci_msix_write_tph_tag(pdev, index, tag); 308 350 break; 309 351 case PCI_TPH_LOC_CAP: 310 352 err = write_tag_to_st_table(pdev, index, tag);
+3 -7
drivers/soc/ti/ti_sci_inta_msi.c
··· 103 103 if (ret) 104 104 return ret; 105 105 106 - msi_lock_descs(dev); 106 + guard(msi_descs_lock)(dev); 107 107 nvec = ti_sci_inta_msi_alloc_descs(dev, res); 108 - if (nvec <= 0) { 109 - ret = nvec; 110 - goto unlock; 111 - } 108 + if (nvec <= 0) 109 + return nvec; 112 110 113 111 /* Use alloc ALL as it's unclear whether there are gaps in the indices */ 114 112 ret = msi_domain_alloc_irqs_all_locked(dev, MSI_DEFAULT_DOMAIN, nvec); 115 113 if (ret) 116 114 dev_err(dev, "Failed to allocate IRQs %d\n", ret); 117 - unlock: 118 - msi_unlock_descs(dev); 119 115 return ret; 120 116 } 121 117 EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs);
+48 -37
drivers/ufs/host/ufs-qcom.c
··· 1849 1849 ufshcd_mcq_config_esi(hba, msg); 1850 1850 } 1851 1851 1852 + struct ufs_qcom_irq { 1853 + unsigned int irq; 1854 + unsigned int idx; 1855 + struct ufs_hba *hba; 1856 + }; 1857 + 1852 1858 static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data) 1853 1859 { 1854 - struct msi_desc *desc = data; 1855 - struct device *dev = msi_desc_to_dev(desc); 1856 - struct ufs_hba *hba = dev_get_drvdata(dev); 1857 - u32 id = desc->msi_index; 1858 - struct ufs_hw_queue *hwq = &hba->uhq[id]; 1860 + struct ufs_qcom_irq *qi = data; 1861 + struct ufs_hba *hba = qi->hba; 1862 + struct ufs_hw_queue *hwq = &hba->uhq[qi->idx]; 1859 1863 1860 - ufshcd_mcq_write_cqis(hba, 0x1, id); 1864 + ufshcd_mcq_write_cqis(hba, 0x1, qi->idx); 1861 1865 ufshcd_mcq_poll_cqe_lock(hba, hwq); 1862 1866 1863 1867 return IRQ_HANDLED; 1864 1868 } 1865 1869 1870 + static void ufs_qcom_irq_free(struct ufs_qcom_irq *uqi) 1871 + { 1872 + for (struct ufs_qcom_irq *q = uqi; q->irq; q++) 1873 + devm_free_irq(q->hba->dev, q->irq, q->hba); 1874 + 1875 + platform_device_msi_free_irqs_all(uqi->hba->dev); 1876 + devm_kfree(uqi->hba->dev, uqi); 1877 + } 1878 + 1879 + DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *, if (_T) ufs_qcom_irq_free(_T)) 1880 + 1866 1881 static int ufs_qcom_config_esi(struct ufs_hba *hba) 1867 1882 { 1868 1883 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 1869 - struct msi_desc *desc; 1870 - struct msi_desc *failed_desc = NULL; 1871 1884 int nr_irqs, ret; 1872 1885 1873 1886 if (host->esi_enabled) ··· 1891 1878 * 2. Poll queues do not need ESI. 1892 1879 */ 1893 1880 nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL]; 1881 + 1882 + struct ufs_qcom_irq *qi __free(ufs_qcom_irq) = 1883 + devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); 1884 + if (!qi) 1885 + return -ENOMEM; 1886 + /* Preset so __free() has a pointer to hba in all error paths */ 1887 + qi[0].hba = hba; 1888 + 1894 1889 ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs, 1895 1890 ufs_qcom_write_msi_msg); 1896 1891 if (ret) { ··· 1906 1885 return ret; 1907 1886 } 1908 1887 1909 - msi_lock_descs(hba->dev); 1910 - msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) { 1911 - ret = devm_request_irq(hba->dev, desc->irq, 1912 - ufs_qcom_mcq_esi_handler, 1913 - IRQF_SHARED, "qcom-mcq-esi", desc); 1888 + for (int idx = 0; idx < nr_irqs; idx++) { 1889 + qi[idx].irq = msi_get_virq(hba->dev, idx); 1890 + qi[idx].idx = idx; 1891 + qi[idx].hba = hba; 1892 + 1893 + ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler, 1894 + IRQF_SHARED, "qcom-mcq-esi", qi + idx); 1914 1895 if (ret) { 1915 1896 dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n", 1916 - __func__, desc->irq, ret); 1917 - failed_desc = desc; 1918 - break; 1897 + __func__, qi[idx].irq, ret); 1898 + qi[idx].irq = 0; 1899 + return ret; 1919 1900 } 1920 1901 } 1921 - msi_unlock_descs(hba->dev); 1922 1902 1923 - if (ret) { 1924 - /* Rewind */ 1925 - msi_lock_descs(hba->dev); 1926 - msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) { 1927 - if (desc == failed_desc) 1928 - break; 1929 - devm_free_irq(hba->dev, desc->irq, hba); 1930 - } 1931 - msi_unlock_descs(hba->dev); 1932 - platform_device_msi_free_irqs_all(hba->dev); 1933 - } else { 1934 - if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && 1935 - host->hw_ver.step == 0) 1936 - ufshcd_rmwl(hba, ESI_VEC_MASK, 1937 - FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), 1938 - REG_UFS_CFG3); 1939 - ufshcd_mcq_enable_esi(hba); 1940 - host->esi_enabled = true; 1903 + retain_and_null_ptr(qi); 1904 + 1905 + if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && 1906 + host->hw_ver.step == 0) { 1907 + ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), 1908 + REG_UFS_CFG3); 1941 1909 } 1942 - 1943 - return ret; 1910 + ufshcd_mcq_enable_esi(hba); 1911 + host->esi_enabled = true; 1912 + return 0; 1944 1913 } 1945 1914 1946 1915 static u32 ufs_qcom_freq_to_gear_speed(struct ufs_hba *hba, unsigned long freq)
+19
include/linux/cleanup.h
··· 216 216 217 217 #define return_ptr(p) return no_free_ptr(p) 218 218 219 + /* 220 + * Only for situations where an allocation is handed in to another function 221 + * and consumed by that function on success. 222 + * 223 + * struct foo *f __free(kfree) = kzalloc(sizeof(*f), GFP_KERNEL); 224 + * 225 + * setup(f); 226 + * if (some_condition) 227 + * return -EINVAL; 228 + * .... 229 + * ret = bar(f); 230 + * if (!ret) 231 + * retain_and_null_ptr(f); 232 + * return ret; 233 + * 234 + * After retain_and_null_ptr(f) the variable f is NULL and cannot be 235 + * dereferenced anymore. 236 + */ 237 + #define retain_and_null_ptr(p) ((void)__get_and_null(p, NULL)) 219 238 220 239 /* 221 240 * DEFINE_CLASS(name, type, exit, init, init_args...):
+9
include/linux/irqdomain.h
··· 209 209 /* Irq domain must destroy generic chips when removed */ 210 210 IRQ_DOMAIN_FLAG_DESTROY_GC = (1 << 10), 211 211 212 + /* Address and data pair is mutable when irq_set_affinity() */ 213 + IRQ_DOMAIN_FLAG_MSI_IMMUTABLE = (1 << 11), 214 + 212 215 /* 213 216 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved 214 217 * for implementation specific purposes and ignored by the ··· 258 255 } 259 256 260 257 void irq_domain_free_fwnode(struct fwnode_handle *fwnode); 258 + 259 + DEFINE_FREE(irq_domain_free_fwnode, struct fwnode_handle *, if (_T) irq_domain_free_fwnode(_T)) 261 260 262 261 struct irq_domain_chip_generic_info; 263 262 ··· 632 627 return domain->flags & IRQ_DOMAIN_FLAG_MSI_DEVICE; 633 628 } 634 629 630 + static inline bool irq_domain_is_msi_immutable(struct irq_domain *domain) 631 + { 632 + return domain->flags & IRQ_DOMAIN_FLAG_MSI_IMMUTABLE; 633 + } 635 634 #else /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 636 635 static inline int irq_domain_alloc_irqs(struct irq_domain *domain, unsigned int nr_irqs, 637 636 int node, void *arg)
+19 -4
include/linux/msi.h
··· 229 229 230 230 int msi_setup_device_data(struct device *dev); 231 231 232 - void msi_lock_descs(struct device *dev); 233 - void msi_unlock_descs(struct device *dev); 232 + void __msi_lock_descs(struct device *dev); 233 + void __msi_unlock_descs(struct device *dev); 234 + 235 + DEFINE_LOCK_GUARD_1(msi_descs_lock, struct device, __msi_lock_descs(_T->lock), 236 + __msi_unlock_descs(_T->lock)); 234 237 235 238 struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, 236 239 enum msi_desc_filter filter); ··· 423 420 * @msi_init: Domain specific init function for MSI interrupts 424 421 * @msi_free: Domain specific function to free a MSI interrupts 425 422 * @msi_prepare: Prepare the allocation of the interrupts in the domain 423 + * @msi_teardown: Reverse the effects of @msi_prepare 426 424 * @prepare_desc: Optional function to prepare the allocated MSI descriptor 427 425 * in the domain 428 426 * @set_desc: Set the msi descriptor for an interrupt ··· 439 435 * @get_hwirq, @msi_init and @msi_free are callbacks used by the underlying 440 436 * irqdomain. 441 437 * 442 - * @msi_check, @msi_prepare, @prepare_desc and @set_desc are callbacks used by the 443 - * msi_domain_alloc/free_irqs*() variants. 438 + * @msi_check, @msi_prepare, @msi_teardown, @prepare_desc and 439 + * @set_desc are callbacks used by the msi_domain_alloc/free_irqs*() 440 + * variants. 444 441 * 445 442 * @domain_alloc_irqs, @domain_free_irqs can be used to override the 446 443 * default allocation/free functions (__msi_domain_alloc/free_irqs). This ··· 463 458 int (*msi_prepare)(struct irq_domain *domain, 464 459 struct device *dev, int nvec, 465 460 msi_alloc_info_t *arg); 461 + void (*msi_teardown)(struct irq_domain *domain, 462 + msi_alloc_info_t *arg); 466 463 void (*prepare_desc)(struct irq_domain *domain, msi_alloc_info_t *arg, 467 464 struct msi_desc *desc); 468 465 void (*set_desc)(msi_alloc_info_t *arg, ··· 493 486 * @handler: Optional: associated interrupt flow handler 494 487 * @handler_data: Optional: associated interrupt flow handler data 495 488 * @handler_name: Optional: associated interrupt flow handler name 489 + * @alloc_data: Optional: associated interrupt allocation data 496 490 * @data: Optional: domain specific data 497 491 */ 498 492 struct msi_domain_info { ··· 506 498 irq_flow_handler_t handler; 507 499 void *handler_data; 508 500 const char *handler_name; 501 + msi_alloc_info_t *alloc_data; 509 502 void *data; 510 503 }; 511 504 ··· 516 507 * @chip: Interrupt chip for this domain 517 508 * @ops: MSI domain ops 518 509 * @info: MSI domain info data 510 + * @alloc_info: MSI domain allocation data (architecture specific) 519 511 */ 520 512 struct msi_domain_template { 521 513 char name[48]; 522 514 struct irq_chip chip; 523 515 struct msi_domain_ops ops; 524 516 struct msi_domain_info info; 517 + msi_alloc_info_t alloc_info; 525 518 }; 526 519 527 520 /* ··· 635 624 struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, 636 625 struct msi_domain_info *info, 637 626 struct irq_domain *parent); 627 + 628 + struct irq_domain_info; 629 + struct irq_domain *msi_create_parent_irq_domain(struct irq_domain_info *info, 630 + const struct msi_parent_ops *msi_parent_ops); 638 631 639 632 bool msi_create_device_irq_domain(struct device *dev, unsigned int domid, 640 633 const struct msi_domain_template *template,
+2 -2
include/linux/pci.h
··· 1671 1671 int pci_msix_vec_count(struct pci_dev *dev); 1672 1672 void pci_disable_msix(struct pci_dev *dev); 1673 1673 void pci_restore_msi_state(struct pci_dev *dev); 1674 - int pci_msi_enabled(void); 1674 + bool pci_msi_enabled(void); 1675 1675 int pci_enable_msi(struct pci_dev *dev); 1676 1676 int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, 1677 1677 int minvec, int maxvec); ··· 1704 1704 static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; } 1705 1705 static inline void pci_disable_msix(struct pci_dev *dev) { } 1706 1706 static inline void pci_restore_msi_state(struct pci_dev *dev) { } 1707 - static inline int pci_msi_enabled(void) { return 0; } 1707 + static inline bool pci_msi_enabled(void) { return false; } 1708 1708 static inline int pci_enable_msi(struct pci_dev *dev) 1709 1709 { return -ENOSYS; } 1710 1710 static inline int pci_enable_msix_range(struct pci_dev *dev,
+115 -77
kernel/irq/msi.c
··· 59 59 static void msi_domain_free_locked(struct device *dev, struct msi_ctrl *ctrl); 60 60 static unsigned int msi_domain_get_hwsize(struct device *dev, unsigned int domid); 61 61 static inline int msi_sysfs_create_group(struct device *dev); 62 - 62 + static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, 63 + int nvec, msi_alloc_info_t *arg); 63 64 64 65 /** 65 66 * msi_alloc_desc - Allocate an initialized msi_desc ··· 344 343 } 345 344 346 345 /** 347 - * msi_lock_descs - Lock the MSI descriptor storage of a device 346 + * __msi_lock_descs - Lock the MSI descriptor storage of a device 348 347 * @dev: Device to operate on 348 + * 349 + * Internal function for guard(msi_descs_lock). Don't use in code. 349 350 */ 350 - void msi_lock_descs(struct device *dev) 351 + void __msi_lock_descs(struct device *dev) 351 352 { 352 353 mutex_lock(&dev->msi.data->mutex); 353 354 } 354 - EXPORT_SYMBOL_GPL(msi_lock_descs); 355 + EXPORT_SYMBOL_GPL(__msi_lock_descs); 355 356 356 357 /** 357 - * msi_unlock_descs - Unlock the MSI descriptor storage of a device 358 + * __msi_unlock_descs - Unlock the MSI descriptor storage of a device 358 359 * @dev: Device to operate on 360 + * 361 + * Internal function for guard(msi_descs_lock). Don't use in code. 359 362 */ 360 - void msi_unlock_descs(struct device *dev) 363 + void __msi_unlock_descs(struct device *dev) 361 364 { 362 365 /* Invalidate the index which was cached by the iterator */ 363 366 dev->msi.data->__iter_idx = MSI_XA_MAX_INDEX; 364 367 mutex_unlock(&dev->msi.data->mutex); 365 368 } 366 - EXPORT_SYMBOL_GPL(msi_unlock_descs); 369 + EXPORT_SYMBOL_GPL(__msi_unlock_descs); 367 370 368 371 static struct msi_desc *msi_find_desc(struct msi_device_data *md, unsigned int domid, 369 372 enum msi_desc_filter filter) ··· 453 448 unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index) 454 449 { 455 450 struct msi_desc *desc; 456 - unsigned int ret = 0; 457 451 bool pcimsi = false; 458 452 struct xarray *xa; 459 453 ··· 466 462 if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN) 467 463 pcimsi = to_pci_dev(dev)->msi_enabled; 468 464 469 - msi_lock_descs(dev); 465 + guard(msi_descs_lock)(dev); 470 466 xa = &dev->msi.data->__domains[domid].store; 471 467 desc = xa_load(xa, pcimsi ? 0 : index); 472 468 if (desc && desc->irq) { ··· 475 471 * PCI-MSIX and platform MSI use a descriptor per 476 472 * interrupt. 477 473 */ 478 - if (pcimsi) { 479 - if (index < desc->nvec_used) 480 - ret = desc->irq + index; 481 - } else { 482 - ret = desc->irq; 483 - } 474 + if (!pcimsi) 475 + return desc->irq; 476 + if (index < desc->nvec_used) 477 + return desc->irq + index; 484 478 } 485 - 486 - msi_unlock_descs(dev); 487 - return ret; 479 + return 0; 488 480 } 489 481 EXPORT_SYMBOL_GPL(msi_domain_get_virq); 490 482 ··· 796 796 return 0; 797 797 } 798 798 799 + static void msi_domain_ops_teardown(struct irq_domain *domain, msi_alloc_info_t *arg) 800 + { 801 + } 802 + 799 803 static void msi_domain_ops_set_desc(msi_alloc_info_t *arg, 800 804 struct msi_desc *desc) 801 805 { ··· 825 821 .get_hwirq = msi_domain_ops_get_hwirq, 826 822 .msi_init = msi_domain_ops_init, 827 823 .msi_prepare = msi_domain_ops_prepare, 824 + .msi_teardown = msi_domain_ops_teardown, 828 825 .set_desc = msi_domain_ops_set_desc, 829 826 }; 830 827 ··· 847 842 ops->msi_init = msi_domain_ops_default.msi_init; 848 843 if (ops->msi_prepare == NULL) 849 844 ops->msi_prepare = msi_domain_ops_default.msi_prepare; 845 + if (ops->msi_teardown == NULL) 846 + ops->msi_teardown = msi_domain_ops_default.msi_teardown; 850 847 if (ops->set_desc == NULL) 851 848 ops->set_desc = msi_domain_ops_default.set_desc; 852 849 } ··· 910 903 { 911 904 return __msi_create_irq_domain(fwnode, info, 0, parent); 912 905 } 906 + 907 + /** 908 + * msi_create_parent_irq_domain - Create an MSI-parent interrupt domain 909 + * @info: MSI irqdomain creation info 910 + * @msi_parent_ops: MSI parent callbacks and configuration 911 + * 912 + * Return: pointer to the created &struct irq_domain or %NULL on failure 913 + */ 914 + struct irq_domain *msi_create_parent_irq_domain(struct irq_domain_info *info, 915 + const struct msi_parent_ops *msi_parent_ops) 916 + { 917 + struct irq_domain *d; 918 + 919 + info->hwirq_max = max(info->hwirq_max, info->size); 920 + info->size = info->hwirq_max; 921 + info->domain_flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 922 + info->bus_token = msi_parent_ops->bus_select_token; 923 + 924 + d = irq_domain_instantiate(info); 925 + if (IS_ERR(d)) 926 + return NULL; 927 + 928 + d->msi_parent_ops = msi_parent_ops; 929 + return d; 930 + } 931 + EXPORT_SYMBOL_GPL(msi_create_parent_irq_domain); 913 932 914 933 /** 915 934 * msi_parent_init_dev_msi_info - Delegate initialization of device MSI info down ··· 1031 998 void *chip_data) 1032 999 { 1033 1000 struct irq_domain *domain, *parent = dev->msi.domain; 1034 - struct fwnode_handle *fwnode, *fwnalloced = NULL; 1035 - struct msi_domain_template *bundle; 1036 1001 const struct msi_parent_ops *pops; 1002 + struct fwnode_handle *fwnode; 1037 1003 1038 1004 if (!irq_domain_is_msi_parent(parent)) 1039 1005 return false; ··· 1040 1008 if (domid >= MSI_MAX_DEVICE_IRQDOMAINS) 1041 1009 return false; 1042 1010 1043 - bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL); 1011 + struct msi_domain_template *bundle __free(kfree) = 1012 + kmemdup(template, sizeof(*bundle), GFP_KERNEL); 1044 1013 if (!bundle) 1045 1014 return false; 1046 1015 ··· 1050 1017 bundle->info.ops = &bundle->ops; 1051 1018 bundle->info.data = domain_data; 1052 1019 bundle->info.chip_data = chip_data; 1020 + bundle->info.alloc_data = &bundle->alloc_info; 1053 1021 1054 1022 pops = parent->msi_parent_ops; 1055 1023 snprintf(bundle->name, sizeof(bundle->name), "%s%s-%s", ··· 1065 1031 * node as they are not guaranteed to have a fwnode. They are never 1066 1032 * looked up and always handled in the context of the device. 1067 1033 */ 1068 - if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE) 1069 - fwnode = dev->fwnode; 1034 + struct fwnode_handle *fwnode_alloced __free(irq_domain_free_fwnode) = NULL; 1035 + 1036 + if (!(bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)) 1037 + fwnode = fwnode_alloced = irq_domain_alloc_named_fwnode(bundle->name); 1070 1038 else 1071 - fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name); 1039 + fwnode = dev->fwnode; 1072 1040 1073 1041 if (!fwnode) 1074 - goto free_bundle; 1042 + return false; 1075 1043 1076 1044 if (msi_setup_device_data(dev)) 1077 - goto free_fwnode; 1045 + return false; 1078 1046 1079 - msi_lock_descs(dev); 1080 - 1047 + guard(msi_descs_lock)(dev); 1081 1048 if (WARN_ON_ONCE(msi_get_device_domain(dev, domid))) 1082 - goto fail; 1049 + return false; 1083 1050 1084 1051 if (!pops->init_dev_msi_info(dev, parent, parent, &bundle->info)) 1085 - goto fail; 1052 + return false; 1086 1053 1087 1054 domain = __msi_create_irq_domain(fwnode, &bundle->info, IRQ_DOMAIN_FLAG_MSI_DEVICE, parent); 1088 1055 if (!domain) 1089 - goto fail; 1056 + return false; 1090 1057 1091 1058 domain->dev = dev; 1092 1059 dev->msi.data->__domains[domid].domain = domain; 1093 - msi_unlock_descs(dev); 1094 - return true; 1095 1060 1096 - fail: 1097 - msi_unlock_descs(dev); 1098 - free_fwnode: 1099 - irq_domain_free_fwnode(fwnalloced); 1100 - free_bundle: 1101 - kfree(bundle); 1102 - return false; 1061 + if (msi_domain_prepare_irqs(domain, dev, hwsize, &bundle->alloc_info)) { 1062 + dev->msi.data->__domains[domid].domain = NULL; 1063 + irq_domain_remove(domain); 1064 + return false; 1065 + } 1066 + 1067 + /* @bundle and @fwnode_alloced are now in use. Prevent cleanup */ 1068 + retain_and_null_ptr(bundle); 1069 + retain_and_null_ptr(fwnode_alloced); 1070 + return true; 1103 1071 } 1104 1072 1105 1073 /** ··· 1115 1079 struct msi_domain_info *info; 1116 1080 struct irq_domain *domain; 1117 1081 1118 - msi_lock_descs(dev); 1119 - 1082 + guard(msi_descs_lock)(dev); 1120 1083 domain = msi_get_device_domain(dev, domid); 1121 - 1122 1084 if (!domain || !irq_domain_is_msi_device(domain)) 1123 - goto unlock; 1085 + return; 1124 1086 1125 1087 dev->msi.data->__domains[domid].domain = NULL; 1126 1088 info = domain->host_data; 1089 + 1090 + info->ops->msi_teardown(domain, info->alloc_data); 1091 + 1127 1092 if (irq_domain_is_msi_device(domain)) 1128 1093 fwnode = domain->fwnode; 1129 1094 irq_domain_remove(domain); 1130 1095 irq_domain_free_fwnode(fwnode); 1131 1096 kfree(container_of(info, struct msi_domain_template, info)); 1132 - 1133 - unlock: 1134 - msi_unlock_descs(dev); 1135 1097 } 1136 1098 1137 1099 /** ··· 1145 1111 { 1146 1112 struct msi_domain_info *info; 1147 1113 struct irq_domain *domain; 1148 - bool ret = false; 1149 1114 1150 - msi_lock_descs(dev); 1115 + guard(msi_descs_lock)(dev); 1151 1116 domain = msi_get_device_domain(dev, domid); 1152 1117 if (domain && irq_domain_is_msi_device(domain)) { 1153 1118 info = domain->host_data; 1154 - ret = info->bus_token == bus_token; 1119 + return info->bus_token == bus_token; 1155 1120 } 1156 - msi_unlock_descs(dev); 1157 - return ret; 1121 + return false; 1158 1122 } 1159 1123 1160 1124 static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, ··· 1270 1238 return 0; 1271 1239 } 1272 1240 1241 + static int populate_alloc_info(struct irq_domain *domain, struct device *dev, 1242 + unsigned int nirqs, msi_alloc_info_t *arg) 1243 + { 1244 + struct msi_domain_info *info = domain->host_data; 1245 + 1246 + /* 1247 + * If the caller has provided a template alloc info, use that. Once 1248 + * all users of msi_create_irq_domain() have been eliminated, this 1249 + * should be the only source of allocation information, and the 1250 + * prepare call below should be finally removed. 1251 + */ 1252 + if (!info->alloc_data) 1253 + return msi_domain_prepare_irqs(domain, dev, nirqs, arg); 1254 + 1255 + *arg = *info->alloc_data; 1256 + return 0; 1257 + } 1258 + 1273 1259 static int __msi_domain_alloc_irqs(struct device *dev, struct irq_domain *domain, 1274 1260 struct msi_ctrl *ctrl) 1275 1261 { ··· 1300 1250 unsigned long idx; 1301 1251 int i, ret, virq; 1302 1252 1303 - ret = msi_domain_prepare_irqs(domain, dev, ctrl->nirqs, &arg); 1253 + ret = populate_alloc_info(domain, dev, ctrl->nirqs, &arg); 1304 1254 if (ret) 1305 1255 return ret; 1306 1256 ··· 1441 1391 int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, 1442 1392 unsigned int first, unsigned int last) 1443 1393 { 1444 - int ret; 1445 1394 1446 - msi_lock_descs(dev); 1447 - ret = msi_domain_alloc_irqs_range_locked(dev, domid, first, last); 1448 - msi_unlock_descs(dev); 1449 - return ret; 1395 + guard(msi_descs_lock)(dev); 1396 + return msi_domain_alloc_irqs_range_locked(dev, domid, first, last); 1450 1397 } 1451 1398 EXPORT_SYMBOL_GPL(msi_domain_alloc_irqs_range); 1452 1399 ··· 1547 1500 const struct irq_affinity_desc *affdesc, 1548 1501 union msi_instance_cookie *icookie) 1549 1502 { 1550 - struct msi_map map; 1551 - 1552 - msi_lock_descs(dev); 1553 - map = __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie); 1554 - msi_unlock_descs(dev); 1555 - return map; 1503 + guard(msi_descs_lock)(dev); 1504 + return __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie); 1556 1505 } 1557 1506 1558 1507 /** ··· 1585 1542 1586 1543 icookie.value = ((u64)type << 32) | hwirq; 1587 1544 1588 - msi_lock_descs(dev); 1545 + guard(msi_descs_lock)(dev); 1589 1546 if (WARN_ON_ONCE(msi_get_device_domain(dev, domid) != domain)) 1590 1547 map.index = -EINVAL; 1591 1548 else 1592 1549 map = __msi_domain_alloc_irq_at(dev, domid, MSI_ANY_INDEX, NULL, &icookie); 1593 - msi_unlock_descs(dev); 1594 - 1595 1550 return map.index >= 0 ? map.virq : map.index; 1596 1551 } 1597 1552 ··· 1682 1641 void msi_domain_free_irqs_range(struct device *dev, unsigned int domid, 1683 1642 unsigned int first, unsigned int last) 1684 1643 { 1685 - msi_lock_descs(dev); 1644 + guard(msi_descs_lock)(dev); 1686 1645 msi_domain_free_irqs_range_locked(dev, domid, first, last); 1687 - msi_unlock_descs(dev); 1688 1646 } 1689 1647 EXPORT_SYMBOL_GPL(msi_domain_free_irqs_all); 1690 1648 ··· 1713 1673 */ 1714 1674 void msi_domain_free_irqs_all(struct device *dev, unsigned int domid) 1715 1675 { 1716 - msi_lock_descs(dev); 1676 + guard(msi_descs_lock)(dev); 1717 1677 msi_domain_free_irqs_all_locked(dev, domid); 1718 - msi_unlock_descs(dev); 1719 1678 } 1720 1679 1721 1680 /** ··· 1733 1694 if (WARN_ON_ONCE(!dev || !desc || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI)) 1734 1695 return; 1735 1696 1736 - msi_lock_descs(dev); 1737 - if (!WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) { 1738 - msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index, 1739 - desc->msi_index); 1740 - } 1741 - msi_unlock_descs(dev); 1697 + guard(msi_descs_lock)(dev); 1698 + if (WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) 1699 + return; 1700 + msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index, 1701 + desc->msi_index); 1742 1702 } 1743 1703 1744 1704 /**