Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCI Message Signaled Interrupt (MSI) - irqdomain support
0004  */
0005 #include <linux/acpi_iort.h>
0006 #include <linux/irqdomain.h>
0007 #include <linux/of_irq.h>
0008 
0009 #include "msi.h"
0010 
0011 int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
0012 {
0013     struct irq_domain *domain;
0014 
0015     domain = dev_get_msi_domain(&dev->dev);
0016     if (domain && irq_domain_is_hierarchy(domain))
0017         return msi_domain_alloc_irqs_descs_locked(domain, &dev->dev, nvec);
0018 
0019     return pci_msi_legacy_setup_msi_irqs(dev, nvec, type);
0020 }
0021 
0022 void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
0023 {
0024     struct irq_domain *domain;
0025 
0026     domain = dev_get_msi_domain(&dev->dev);
0027     if (domain && irq_domain_is_hierarchy(domain))
0028         msi_domain_free_irqs_descs_locked(domain, &dev->dev);
0029     else
0030         pci_msi_legacy_teardown_msi_irqs(dev);
0031     msi_free_msi_descs(&dev->dev);
0032 }
0033 
0034 /**
0035  * pci_msi_domain_write_msg - Helper to write MSI message to PCI config space
0036  * @irq_data:   Pointer to interrupt data of the MSI interrupt
0037  * @msg:    Pointer to the message
0038  */
0039 static void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
0040 {
0041     struct msi_desc *desc = irq_data_get_msi_desc(irq_data);
0042 
0043     /*
0044      * For MSI-X desc->irq is always equal to irq_data->irq. For
0045      * MSI only the first interrupt of MULTI MSI passes the test.
0046      */
0047     if (desc->irq == irq_data->irq)
0048         __pci_write_msi_msg(desc, msg);
0049 }
0050 
0051 /**
0052  * pci_msi_domain_calc_hwirq - Generate a unique ID for an MSI source
0053  * @desc:   Pointer to the MSI descriptor
0054  *
0055  * The ID number is only used within the irqdomain.
0056  */
0057 static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc)
0058 {
0059     struct pci_dev *dev = msi_desc_to_pci_dev(desc);
0060 
0061     return (irq_hw_number_t)desc->msi_index |
0062         pci_dev_id(dev) << 11 |
0063         (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
0064 }
0065 
0066 static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
0067 {
0068     return !desc->pci.msi_attrib.is_msix && desc->nvec_used > 1;
0069 }
0070 
0071 /**
0072  * pci_msi_domain_check_cap - Verify that @domain supports the capabilities
0073  *                for @dev
0074  * @domain: The interrupt domain to check
0075  * @info:   The domain info for verification
0076  * @dev:    The device to check
0077  *
0078  * Returns:
0079  *  0 if the functionality is supported
0080  *  1 if Multi MSI is requested, but the domain does not support it
0081  *  -ENOTSUPP otherwise
0082  */
0083 static int pci_msi_domain_check_cap(struct irq_domain *domain,
0084                     struct msi_domain_info *info,
0085                     struct device *dev)
0086 {
0087     struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL);
0088 
0089     /* Special handling to support __pci_enable_msi_range() */
0090     if (pci_msi_desc_is_multi_msi(desc) &&
0091         !(info->flags & MSI_FLAG_MULTI_PCI_MSI))
0092         return 1;
0093 
0094     if (desc->pci.msi_attrib.is_msix) {
0095         if (!(info->flags & MSI_FLAG_PCI_MSIX))
0096             return -ENOTSUPP;
0097 
0098         if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) {
0099             unsigned int idx = 0;
0100 
0101             /* Check for gaps in the entry indices */
0102             msi_for_each_desc(desc, dev, MSI_DESC_ALL) {
0103                 if (desc->msi_index != idx++)
0104                     return -ENOTSUPP;
0105             }
0106         }
0107     }
0108     return 0;
0109 }
0110 
0111 static void pci_msi_domain_set_desc(msi_alloc_info_t *arg,
0112                     struct msi_desc *desc)
0113 {
0114     arg->desc = desc;
0115     arg->hwirq = pci_msi_domain_calc_hwirq(desc);
0116 }
0117 
0118 static struct msi_domain_ops pci_msi_domain_ops_default = {
0119     .set_desc   = pci_msi_domain_set_desc,
0120     .msi_check  = pci_msi_domain_check_cap,
0121 };
0122 
0123 static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info)
0124 {
0125     struct msi_domain_ops *ops = info->ops;
0126 
0127     if (ops == NULL) {
0128         info->ops = &pci_msi_domain_ops_default;
0129     } else {
0130         if (ops->set_desc == NULL)
0131             ops->set_desc = pci_msi_domain_set_desc;
0132         if (ops->msi_check == NULL)
0133             ops->msi_check = pci_msi_domain_check_cap;
0134     }
0135 }
0136 
0137 static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
0138 {
0139     struct irq_chip *chip = info->chip;
0140 
0141     BUG_ON(!chip);
0142     if (!chip->irq_write_msi_msg)
0143         chip->irq_write_msi_msg = pci_msi_domain_write_msg;
0144     if (!chip->irq_mask)
0145         chip->irq_mask = pci_msi_mask_irq;
0146     if (!chip->irq_unmask)
0147         chip->irq_unmask = pci_msi_unmask_irq;
0148 }
0149 
0150 /**
0151  * pci_msi_create_irq_domain - Create a MSI interrupt domain
0152  * @fwnode: Optional fwnode of the interrupt controller
0153  * @info:   MSI domain info
0154  * @parent: Parent irq domain
0155  *
0156  * Updates the domain and chip ops and creates a MSI interrupt domain.
0157  *
0158  * Returns:
0159  * A domain pointer or NULL in case of failure.
0160  */
0161 struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
0162                          struct msi_domain_info *info,
0163                          struct irq_domain *parent)
0164 {
0165     struct irq_domain *domain;
0166 
0167     if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE))
0168         info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
0169 
0170     if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
0171         pci_msi_domain_update_dom_ops(info);
0172     if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
0173         pci_msi_domain_update_chip_ops(info);
0174 
0175     info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS;
0176     if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE))
0177         info->flags |= MSI_FLAG_MUST_REACTIVATE;
0178 
0179     /* PCI-MSI is oneshot-safe */
0180     info->chip->flags |= IRQCHIP_ONESHOT_SAFE;
0181 
0182     domain = msi_create_irq_domain(fwnode, info, parent);
0183     if (!domain)
0184         return NULL;
0185 
0186     irq_domain_update_bus_token(domain, DOMAIN_BUS_PCI_MSI);
0187     return domain;
0188 }
0189 EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain);
0190 
0191 /*
0192  * Users of the generic MSI infrastructure expect a device to have a single ID,
0193  * so with DMA aliases we have to pick the least-worst compromise. Devices with
0194  * DMA phantom functions tend to still emit MSIs from the real function number,
0195  * so we ignore those and only consider topological aliases where either the
0196  * alias device or RID appears on a different bus number. We also make the
0197  * reasonable assumption that bridges are walked in an upstream direction (so
0198  * the last one seen wins), and the much braver assumption that the most likely
0199  * case is that of PCI->PCIe so we should always use the alias RID. This echoes
0200  * the logic from intel_irq_remapping's set_msi_sid(), which presumably works
0201  * well enough in practice; in the face of the horrible PCIe<->PCI-X conditions
0202  * for taking ownership all we can really do is close our eyes and hope...
0203  */
0204 static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data)
0205 {
0206     u32 *pa = data;
0207     u8 bus = PCI_BUS_NUM(*pa);
0208 
0209     if (pdev->bus->number != bus || PCI_BUS_NUM(alias) != bus)
0210         *pa = alias;
0211 
0212     return 0;
0213 }
0214 
0215 /**
0216  * pci_msi_domain_get_msi_rid - Get the MSI requester id (RID)
0217  * @domain: The interrupt domain
0218  * @pdev:   The PCI device.
0219  *
0220  * The RID for a device is formed from the alias, with a firmware
0221  * supplied mapping applied
0222  *
0223  * Returns: The RID.
0224  */
0225 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
0226 {
0227     struct device_node *of_node;
0228     u32 rid = pci_dev_id(pdev);
0229 
0230     pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
0231 
0232     of_node = irq_domain_get_of_node(domain);
0233     rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) :
0234             iort_msi_map_id(&pdev->dev, rid);
0235 
0236     return rid;
0237 }
0238 
0239 /**
0240  * pci_msi_get_device_domain - Get the MSI domain for a given PCI device
0241  * @pdev:   The PCI device
0242  *
0243  * Use the firmware data to find a device-specific MSI domain
0244  * (i.e. not one that is set as a default).
0245  *
0246  * Returns: The corresponding MSI domain or NULL if none has been found.
0247  */
0248 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
0249 {
0250     struct irq_domain *dom;
0251     u32 rid = pci_dev_id(pdev);
0252 
0253     pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
0254     dom = of_msi_map_get_device_domain(&pdev->dev, rid, DOMAIN_BUS_PCI_MSI);
0255     if (!dom)
0256         dom = iort_get_device_domain(&pdev->dev, rid,
0257                          DOMAIN_BUS_PCI_MSI);
0258     return dom;
0259 }
0260 
0261 /**
0262  * pci_dev_has_special_msi_domain - Check whether the device is handled by
0263  *                  a non-standard PCI-MSI domain
0264  * @pdev:   The PCI device to check.
0265  *
0266  * Returns: True if the device irqdomain or the bus irqdomain is
0267  * non-standard PCI/MSI.
0268  */
0269 bool pci_dev_has_special_msi_domain(struct pci_dev *pdev)
0270 {
0271     struct irq_domain *dom = dev_get_msi_domain(&pdev->dev);
0272 
0273     if (!dom)
0274         dom = dev_get_msi_domain(&pdev->bus->dev);
0275 
0276     if (!dom)
0277         return true;
0278 
0279     return dom->bus_token != DOMAIN_BUS_PCI_MSI;
0280 }