On Fri, Nov 11, 2022 at 02:58:57PM +0100, Thomas Gleixner wrote: > Single vector allocation which allocates the next free index in the IMS > space. The free function releases. > > All allocated vectors are released also via pci_free_vectors() which is > also releasing MSI/MSI-X vectors. > > Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Acked-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> I would probably capitalize "ID" in the function comment below, but either way. > --- > drivers/pci/msi/api.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/pci.h | 3 +++ > 2 files changed, 53 insertions(+) > > --- a/drivers/pci/msi/api.c > +++ b/drivers/pci/msi/api.c > @@ -361,6 +361,56 @@ const struct cpumask *pci_irq_get_affini > EXPORT_SYMBOL(pci_irq_get_affinity); > > /** > + * pci_ims_alloc_irq - Allocate an interrupt on a PCI/IMS interrupt domain > + * @dev: The PCI device to operate on > + * @cookie: Pointer to an IMS implementation specific device cookie > + * (PASID, queue id, pointer...). The cookie content is stored > + * in the MSI descriptor for the interrupt chip callbacks or > + * domain specific setup functions > + * @affdesc: Optional pointer to an interrupt affinity descriptor > + * > + * Return: A struct msi_map > + * > + * On success msi_map::index contains the allocated index (>= 0) and > + * msi_map::virq the allocated Linux interrupt number (> 0). > + * > + * On fail msi_map::index contains the error code and msi_map::virq > + * is set to 0. > + * > + * Note: There is no index for IMS allocations as IMS is an implementation > + * specific storage and does not have any direct associations between > + * index, which might be a pure software construct, and device > + * functionality. This association is established by the driver either > + * via the index - if there is a hardware table - or in case of purely > + * software managed IMS implementation the association happens via > + * the irq_write_msi_msg() callback of the implementation specific > + * interrupt chip, which utilizes the provided @cookie to store the MSI > + * message in the appropriate place. > + */ > +struct msi_map pci_ims_alloc_irq(struct pci_dev *dev, union msi_dev_cookie *cookie, > + const struct irq_affinity_desc *affdesc) > +{ > + return msi_domain_alloc_irq_at(&dev->dev, MSI_SECONDARY_DOMAIN, MSI_ANY_INDEX, > + affdesc, cookie); > +} > +EXPORT_SYMBOL_GPL(pci_ims_alloc_irq); > + > +/** > + * pci_ims_free_irq - Allocate an interrupt on a PCI/IMS interrupt domain > + * which was allocated via pci_ims_alloc_irq() > + * @dev: The PCI device to operate on > + * @map: A struct msi_map describing the interrupt to free as > + * returned from pci_ims_alloc_irq() > + */ > +void pci_ims_free_irq(struct pci_dev *dev, struct msi_map map) > +{ > + if (WARN_ON_ONCE(map.index < 0 || !map.virq)) > + return; > + msi_domain_free_irqs_range(&dev->dev, MSI_SECONDARY_DOMAIN, map.index, map.index); > +} > +EXPORT_SYMBOL_GPL(pci_ims_free_irq); > + > +/** > * pci_free_irq_vectors() - Free previously allocated IRQs for a device > * @dev: the PCI device to operate on > * > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -2485,6 +2485,9 @@ struct msi_domain_template; > > bool pci_create_ims_domain(struct pci_dev *pdev, const struct msi_domain_template *template, > unsigned int hwsize, void *data); > +struct msi_map pci_ims_alloc_irq(struct pci_dev *pdev, union msi_dev_cookie *cookie, > + const struct irq_affinity_desc *affdesc); > +void pci_ims_free_irq(struct pci_dev *pdev, struct msi_map map); > > #include <linux/dma-mapping.h> > >