1 // SPDX-License-Identifier: GPL-2.0
3 * PCI Message Signaled Interrupt (MSI) - irqdomain support
5 #include <linux/acpi_iort.h>
6 #include <linux/irqdomain.h>
7 #include <linux/of_irq.h>
11 int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
13 struct irq_domain *domain;
15 domain = dev_get_msi_domain(&dev->dev);
16 if (domain && irq_domain_is_hierarchy(domain))
17 return msi_domain_alloc_irqs_descs_locked(domain, &dev->dev, nvec);
19 return pci_msi_legacy_setup_msi_irqs(dev, nvec, type);
22 void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
24 struct irq_domain *domain;
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);
30 pci_msi_legacy_teardown_msi_irqs(dev);
31 msi_free_msi_descs(&dev->dev);
36 * pci_msi_domain_write_msg - Helper to write MSI message to PCI config space
37 * @irq_data: Pointer to interrupt data of the MSI interrupt
38 * @msg: Pointer to the message
40 static void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
42 struct msi_desc *desc = irq_data_get_msi_desc(irq_data);
45 * For MSI-X desc->irq is always equal to irq_data->irq. For
46 * MSI only the first interrupt of MULTI MSI passes the test.
48 if (desc->irq == irq_data->irq)
49 __pci_write_msi_msg(desc, msg);
53 * pci_msi_domain_calc_hwirq - Generate a unique ID for an MSI source
54 * @desc: Pointer to the MSI descriptor
56 * The ID number is only used within the irqdomain.
58 static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc)
60 struct pci_dev *dev = msi_desc_to_pci_dev(desc);
62 return (irq_hw_number_t)desc->msi_index |
63 pci_dev_id(dev) << 11 |
64 (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
67 static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
69 return !desc->pci.msi_attrib.is_msix && desc->nvec_used > 1;
73 * pci_msi_domain_check_cap - Verify that @domain supports the capabilities
75 * @domain: The interrupt domain to check
76 * @info: The domain info for verification
77 * @dev: The device to check
80 * 0 if the functionality is supported
81 * 1 if Multi MSI is requested, but the domain does not support it
84 static int pci_msi_domain_check_cap(struct irq_domain *domain,
85 struct msi_domain_info *info,
88 struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL);
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))
95 if (desc->pci.msi_attrib.is_msix) {
96 if (!(info->flags & MSI_FLAG_PCI_MSIX))
99 if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) {
100 unsigned int idx = 0;
102 /* Check for gaps in the entry indices */
103 msi_for_each_desc(desc, dev, MSI_DESC_ALL) {
104 if (desc->msi_index != idx++)
112 static void pci_msi_domain_set_desc(msi_alloc_info_t *arg,
113 struct msi_desc *desc)
116 arg->hwirq = pci_msi_domain_calc_hwirq(desc);
119 static struct msi_domain_ops pci_msi_domain_ops_default = {
120 .set_desc = pci_msi_domain_set_desc,
121 .msi_check = pci_msi_domain_check_cap,
124 static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info)
126 struct msi_domain_ops *ops = info->ops;
129 info->ops = &pci_msi_domain_ops_default;
131 if (ops->set_desc == NULL)
132 ops->set_desc = pci_msi_domain_set_desc;
133 if (ops->msi_check == NULL)
134 ops->msi_check = pci_msi_domain_check_cap;
138 static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
140 struct irq_chip *chip = info->chip;
143 if (!chip->irq_write_msi_msg)
144 chip->irq_write_msi_msg = pci_msi_domain_write_msg;
146 chip->irq_mask = pci_msi_mask_irq;
147 if (!chip->irq_unmask)
148 chip->irq_unmask = pci_msi_unmask_irq;
152 * pci_msi_create_irq_domain - Create a MSI interrupt domain
153 * @fwnode: Optional fwnode of the interrupt controller
154 * @info: MSI domain info
155 * @parent: Parent irq domain
157 * Updates the domain and chip ops and creates a MSI interrupt domain.
160 * A domain pointer or NULL in case of failure.
162 struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
163 struct msi_domain_info *info,
164 struct irq_domain *parent)
166 if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE))
167 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
169 if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
170 pci_msi_domain_update_dom_ops(info);
171 if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
172 pci_msi_domain_update_chip_ops(info);
174 /* Let the core code free MSI descriptors when freeing interrupts */
175 info->flags |= MSI_FLAG_FREE_MSI_DESCS;
177 info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS;
178 if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE))
179 info->flags |= MSI_FLAG_MUST_REACTIVATE;
181 /* PCI-MSI is oneshot-safe */
182 info->chip->flags |= IRQCHIP_ONESHOT_SAFE;
183 /* Let the core update the bus token */
184 info->bus_token = DOMAIN_BUS_PCI_MSI;
186 return msi_create_irq_domain(fwnode, info, parent);
188 EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain);
191 * pci_msi_domain_supports - Check for support of a particular feature flag
192 * @pdev: The PCI device to operate on
193 * @feature_mask: The feature mask to check for (full match)
194 * @mode: If ALLOW_LEGACY this grants the feature when there is no irq domain
195 * associated to the device. If DENY_LEGACY the lack of an irq domain
196 * makes the feature unsupported
198 bool pci_msi_domain_supports(struct pci_dev *pdev, unsigned int feature_mask,
199 enum support_mode mode)
201 struct msi_domain_info *info;
202 struct irq_domain *domain;
204 domain = dev_get_msi_domain(&pdev->dev);
206 if (!domain || !irq_domain_is_hierarchy(domain))
207 return mode == ALLOW_LEGACY;
208 info = domain->host_data;
209 return (info->flags & feature_mask) == feature_mask;
213 * Users of the generic MSI infrastructure expect a device to have a single ID,
214 * so with DMA aliases we have to pick the least-worst compromise. Devices with
215 * DMA phantom functions tend to still emit MSIs from the real function number,
216 * so we ignore those and only consider topological aliases where either the
217 * alias device or RID appears on a different bus number. We also make the
218 * reasonable assumption that bridges are walked in an upstream direction (so
219 * the last one seen wins), and the much braver assumption that the most likely
220 * case is that of PCI->PCIe so we should always use the alias RID. This echoes
221 * the logic from intel_irq_remapping's set_msi_sid(), which presumably works
222 * well enough in practice; in the face of the horrible PCIe<->PCI-X conditions
223 * for taking ownership all we can really do is close our eyes and hope...
225 static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data)
228 u8 bus = PCI_BUS_NUM(*pa);
230 if (pdev->bus->number != bus || PCI_BUS_NUM(alias) != bus)
237 * pci_msi_domain_get_msi_rid - Get the MSI requester id (RID)
238 * @domain: The interrupt domain
239 * @pdev: The PCI device.
241 * The RID for a device is formed from the alias, with a firmware
242 * supplied mapping applied
246 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
248 struct device_node *of_node;
249 u32 rid = pci_dev_id(pdev);
251 pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
253 of_node = irq_domain_get_of_node(domain);
254 rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) :
255 iort_msi_map_id(&pdev->dev, rid);
261 * pci_msi_get_device_domain - Get the MSI domain for a given PCI device
262 * @pdev: The PCI device
264 * Use the firmware data to find a device-specific MSI domain
265 * (i.e. not one that is set as a default).
267 * Returns: The corresponding MSI domain or NULL if none has been found.
269 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
271 struct irq_domain *dom;
272 u32 rid = pci_dev_id(pdev);
274 pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
275 dom = of_msi_map_get_device_domain(&pdev->dev, rid, DOMAIN_BUS_PCI_MSI);
277 dom = iort_get_device_domain(&pdev->dev, rid,
283 * pci_dev_has_special_msi_domain - Check whether the device is handled by
284 * a non-standard PCI-MSI domain
285 * @pdev: The PCI device to check.
287 * Returns: True if the device irqdomain or the bus irqdomain is
288 * non-standard PCI/MSI.
290 bool pci_dev_has_special_msi_domain(struct pci_dev *pdev)
292 struct irq_domain *dom = dev_get_msi_domain(&pdev->dev);
295 dom = dev_get_msi_domain(&pdev->bus->dev);
300 return dom->bus_token != DOMAIN_BUS_PCI_MSI;