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 } 32 33 /** 34 * pci_msi_domain_write_msg - Helper to write MSI message to PCI config space 35 * @irq_data: Pointer to interrupt data of the MSI interrupt 36 * @msg: Pointer to the message 37 */ 38 static void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg) 39 { 40 struct msi_desc *desc = irq_data_get_msi_desc(irq_data); 41 42 /* 43 * For MSI-X desc->irq is always equal to irq_data->irq. For 44 * MSI only the first interrupt of MULTI MSI passes the test. 45 */ 46 if (desc->irq == irq_data->irq) 47 __pci_write_msi_msg(desc, msg); 48 } 49 50 /** 51 * pci_msi_domain_calc_hwirq - Generate a unique ID for an MSI source 52 * @desc: Pointer to the MSI descriptor 53 * 54 * The ID number is only used within the irqdomain. 55 */ 56 static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc) 57 { 58 struct pci_dev *dev = msi_desc_to_pci_dev(desc); 59 60 return (irq_hw_number_t)desc->msi_index | 61 pci_dev_id(dev) << 11 | 62 (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27; 63 } 64 65 static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc) 66 { 67 return !desc->pci.msi_attrib.is_msix && desc->nvec_used > 1; 68 } 69 70 /** 71 * pci_msi_domain_check_cap - Verify that @domain supports the capabilities 72 * for @dev 73 * @domain: The interrupt domain to check 74 * @info: The domain info for verification 75 * @dev: The device to check 76 * 77 * Returns: 78 * 0 if the functionality is supported 79 * 1 if Multi MSI is requested, but the domain does not support it 80 * -ENOTSUPP otherwise 81 */ 82 static int pci_msi_domain_check_cap(struct irq_domain *domain, 83 struct msi_domain_info *info, 84 struct device *dev) 85 { 86 struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL); 87 88 /* Special handling to support __pci_enable_msi_range() */ 89 if (pci_msi_desc_is_multi_msi(desc) && 90 !(info->flags & MSI_FLAG_MULTI_PCI_MSI)) 91 return 1; 92 93 if (desc->pci.msi_attrib.is_msix) { 94 if (!(info->flags & MSI_FLAG_PCI_MSIX)) 95 return -ENOTSUPP; 96 97 if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) { 98 unsigned int idx = 0; 99 100 /* Check for gaps in the entry indices */ 101 msi_for_each_desc(desc, dev, MSI_DESC_ALL) { 102 if (desc->msi_index != idx++) 103 return -ENOTSUPP; 104 } 105 } 106 } 107 return 0; 108 } 109 110 static void pci_msi_domain_set_desc(msi_alloc_info_t *arg, 111 struct msi_desc *desc) 112 { 113 arg->desc = desc; 114 arg->hwirq = pci_msi_domain_calc_hwirq(desc); 115 } 116 117 static struct msi_domain_ops pci_msi_domain_ops_default = { 118 .set_desc = pci_msi_domain_set_desc, 119 .msi_check = pci_msi_domain_check_cap, 120 }; 121 122 static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info) 123 { 124 struct msi_domain_ops *ops = info->ops; 125 126 if (ops == NULL) { 127 info->ops = &pci_msi_domain_ops_default; 128 } else { 129 if (ops->set_desc == NULL) 130 ops->set_desc = pci_msi_domain_set_desc; 131 if (ops->msi_check == NULL) 132 ops->msi_check = pci_msi_domain_check_cap; 133 } 134 } 135 136 static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info) 137 { 138 struct irq_chip *chip = info->chip; 139 140 BUG_ON(!chip); 141 if (!chip->irq_write_msi_msg) 142 chip->irq_write_msi_msg = pci_msi_domain_write_msg; 143 if (!chip->irq_mask) 144 chip->irq_mask = pci_msi_mask_irq; 145 if (!chip->irq_unmask) 146 chip->irq_unmask = pci_msi_unmask_irq; 147 } 148 149 /** 150 * pci_msi_create_irq_domain - Create a MSI interrupt domain 151 * @fwnode: Optional fwnode of the interrupt controller 152 * @info: MSI domain info 153 * @parent: Parent irq domain 154 * 155 * Updates the domain and chip ops and creates a MSI interrupt domain. 156 * 157 * Returns: 158 * A domain pointer or NULL in case of failure. 159 */ 160 struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, 161 struct msi_domain_info *info, 162 struct irq_domain *parent) 163 { 164 struct irq_domain *domain; 165 166 if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) 167 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; 168 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); 173 174 info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS | 175 MSI_FLAG_FREE_MSI_DESCS; 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