1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCI Message Signaled Interrupt (MSI) - irqdomain support 4 */ 5 #include <linux/acpi_iort.h> 6 #include <linux/irqdomain.h> 7 #include <linux/of_irq.h> 8 9 #include "msi.h" 10 11 int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 12 { 13 struct irq_domain *domain; 14 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); 18 19 return pci_msi_legacy_setup_msi_irqs(dev, nvec, type); 20 } 21 22 void pci_msi_teardown_msi_irqs(struct pci_dev *dev) 23 { 24 struct irq_domain *domain; 25 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 30 pci_msi_legacy_teardown_msi_irqs(dev); 31 msi_free_msi_descs(&dev->dev); 32 } 33 34 /** 35 * pci_msi_domain_write_msg - Helper to write MSI message to PCI config space 36 * @irq_data: Pointer to interrupt data of the MSI interrupt 37 * @msg: Pointer to the message 38 */ 39 static void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg) 40 { 41 struct msi_desc *desc = irq_data_get_msi_desc(irq_data); 42 43 /* 44 * For MSI-X desc->irq is always equal to irq_data->irq. For 45 * MSI only the first interrupt of MULTI MSI passes the test. 46 */ 47 if (desc->irq == irq_data->irq) 48 __pci_write_msi_msg(desc, msg); 49 } 50 51 /** 52 * pci_msi_domain_calc_hwirq - Generate a unique ID for an MSI source 53 * @desc: Pointer to the MSI descriptor 54 * 55 * The ID number is only used within the irqdomain. 56 */ 57 static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc) 58 { 59 struct pci_dev *dev = msi_desc_to_pci_dev(desc); 60 61 return (irq_hw_number_t)desc->msi_index | 62 pci_dev_id(dev) << 11 | 63 (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27; 64 } 65 66 static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc) 67 { 68 return !desc->pci.msi_attrib.is_msix && desc->nvec_used > 1; 69 } 70 71 /** 72 * pci_msi_domain_check_cap - Verify that @domain supports the capabilities 73 * for @dev 74 * @domain: The interrupt domain to check 75 * @info: The domain info for verification 76 * @dev: The device to check 77 * 78 * Returns: 79 * 0 if the functionality is supported 80 * 1 if Multi MSI is requested, but the domain does not support it 81 * -ENOTSUPP otherwise 82 */ 83 static int pci_msi_domain_check_cap(struct irq_domain *domain, 84 struct msi_domain_info *info, 85 struct device *dev) 86 { 87 struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL); 88 89 /* Special handling to support __pci_enable_msi_range() */ 90 if (pci_msi_desc_is_multi_msi(desc) && 91 !(info->flags & MSI_FLAG_MULTI_PCI_MSI)) 92 return 1; 93 94 if (desc->pci.msi_attrib.is_msix) { 95 if (!(info->flags & MSI_FLAG_PCI_MSIX)) 96 return -ENOTSUPP; 97 98 if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) { 99 unsigned int idx = 0; 100 101 /* Check for gaps in the entry indices */ 102 msi_for_each_desc(desc, dev, MSI_DESC_ALL) { 103 if (desc->msi_index != idx++) 104 return -ENOTSUPP; 105 } 106 } 107 } 108 return 0; 109 } 110 111 static void pci_msi_domain_set_desc(msi_alloc_info_t *arg, 112 struct msi_desc *desc) 113 { 114 arg->desc = desc; 115 arg->hwirq = pci_msi_domain_calc_hwirq(desc); 116 } 117 118 static struct msi_domain_ops pci_msi_domain_ops_default = { 119 .set_desc = pci_msi_domain_set_desc, 120 .msi_check = pci_msi_domain_check_cap, 121 }; 122 123 static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info) 124 { 125 struct msi_domain_ops *ops = info->ops; 126 127 if (ops == NULL) { 128 info->ops = &pci_msi_domain_ops_default; 129 } else { 130 if (ops->set_desc == NULL) 131 ops->set_desc = pci_msi_domain_set_desc; 132 if (ops->msi_check == NULL) 133 ops->msi_check = pci_msi_domain_check_cap; 134 } 135 } 136 137 static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info) 138 { 139 struct irq_chip *chip = info->chip; 140 141 BUG_ON(!chip); 142 if (!chip->irq_write_msi_msg) 143 chip->irq_write_msi_msg = pci_msi_domain_write_msg; 144 if (!chip->irq_mask) 145 chip->irq_mask = pci_msi_mask_irq; 146 if (!chip->irq_unmask) 147 chip->irq_unmask = pci_msi_unmask_irq; 148 } 149 150 /** 151 * pci_msi_create_irq_domain - Create a MSI interrupt domain 152 * @fwnode: Optional fwnode of the interrupt controller 153 * @info: MSI domain info 154 * @parent: Parent irq domain 155 * 156 * Updates the domain and chip ops and creates a MSI interrupt domain. 157 * 158 * Returns: 159 * A domain pointer or NULL in case of failure. 160 */ 161 struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, 162 struct msi_domain_info *info, 163 struct irq_domain *parent) 164 { 165 struct irq_domain *domain; 166 167 if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) 168 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; 169 170 if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) 171 pci_msi_domain_update_dom_ops(info); 172 if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) 173 pci_msi_domain_update_chip_ops(info); 174 175 info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS; 176 if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE)) 177 info->flags |= MSI_FLAG_MUST_REACTIVATE; 178 179 /* PCI-MSI is oneshot-safe */ 180 info->chip->flags |= IRQCHIP_ONESHOT_SAFE; 181 182 domain = msi_create_irq_domain(fwnode, info, parent); 183 if (!domain) 184 return NULL; 185 186 irq_domain_update_bus_token(domain, DOMAIN_BUS_PCI_MSI); 187 return domain; 188 } 189 EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain); 190 191 /* 192 * Users of the generic MSI infrastructure expect a device to have a single ID, 193 * so with DMA aliases we have to pick the least-worst compromise. Devices with 194 * DMA phantom functions tend to still emit MSIs from the real function number, 195 * so we ignore those and only consider topological aliases where either the 196 * alias device or RID appears on a different bus number. We also make the 197 * reasonable assumption that bridges are walked in an upstream direction (so 198 * the last one seen wins), and the much braver assumption that the most likely 199 * case is that of PCI->PCIe so we should always use the alias RID. This echoes 200 * the logic from intel_irq_remapping's set_msi_sid(), which presumably works 201 * well enough in practice; in the face of the horrible PCIe<->PCI-X conditions 202 * for taking ownership all we can really do is close our eyes and hope... 203 */ 204 static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data) 205 { 206 u32 *pa = data; 207 u8 bus = PCI_BUS_NUM(*pa); 208 209 if (pdev->bus->number != bus || PCI_BUS_NUM(alias) != bus) 210 *pa = alias; 211 212 return 0; 213 } 214 215 /** 216 * pci_msi_domain_get_msi_rid - Get the MSI requester id (RID) 217 * @domain: The interrupt domain 218 * @pdev: The PCI device. 219 * 220 * The RID for a device is formed from the alias, with a firmware 221 * supplied mapping applied 222 * 223 * Returns: The RID. 224 */ 225 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev) 226 { 227 struct device_node *of_node; 228 u32 rid = pci_dev_id(pdev); 229 230 pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); 231 232 of_node = irq_domain_get_of_node(domain); 233 rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) : 234 iort_msi_map_id(&pdev->dev, rid); 235 236 return rid; 237 } 238 239 /** 240 * pci_msi_get_device_domain - Get the MSI domain for a given PCI device 241 * @pdev: The PCI device 242 * 243 * Use the firmware data to find a device-specific MSI domain 244 * (i.e. not one that is set as a default). 245 * 246 * Returns: The corresponding MSI domain or NULL if none has been found. 247 */ 248 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) 249 { 250 struct irq_domain *dom; 251 u32 rid = pci_dev_id(pdev); 252 253 pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); 254 dom = of_msi_map_get_device_domain(&pdev->dev, rid, DOMAIN_BUS_PCI_MSI); 255 if (!dom) 256 dom = iort_get_device_domain(&pdev->dev, rid, 257 DOMAIN_BUS_PCI_MSI); 258 return dom; 259 } 260 261 /** 262 * pci_dev_has_special_msi_domain - Check whether the device is handled by 263 * a non-standard PCI-MSI domain 264 * @pdev: The PCI device to check. 265 * 266 * Returns: True if the device irqdomain or the bus irqdomain is 267 * non-standard PCI/MSI. 268 */ 269 bool pci_dev_has_special_msi_domain(struct pci_dev *pdev) 270 { 271 struct irq_domain *dom = dev_get_msi_domain(&pdev->dev); 272 273 if (!dom) 274 dom = dev_get_msi_domain(&pdev->bus->dev); 275 276 if (!dom) 277 return true; 278 279 return dom->bus_token != DOMAIN_BUS_PCI_MSI; 280 } 281