PCI/MSI: Provide pci_ims_alloc/free_irq()
authorThomas Gleixner <tglx@linutronix.de>
Thu, 24 Nov 2022 23:26:31 +0000 (00:26 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 5 Dec 2022 21:22:35 +0000 (22:22 +0100)
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@linutronix.de>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20221124232326.961711347@linutronix.de
drivers/pci/msi/api.c
include/linux/pci.h

index c8816db91e9c389398a9988ccf9b4b6b96aa9308..b8009aa11f3cede0d712c9ba0bc0c98b4287e119 100644 (file)
@@ -365,6 +365,56 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr)
 }
 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
+ * @icookie:   Pointer to an IMS implementation specific cookie for this
+ *             IMS instance (PASID, queue ID, pointer...).
+ *             The cookie content is copied into the MSI descriptor for the
+ *             interrupt chip callbacks or domain specific setup functions.
+ * @affdesc:   Optional pointer to an interrupt affinity descriptor
+ *
+ * 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 @icookie to store the MSI message in
+ * the appropriate place.
+ *
+ * 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.
+ */
+struct msi_map pci_ims_alloc_irq(struct pci_dev *dev, union msi_instance_cookie *icookie,
+                                const struct irq_affinity_desc *affdesc)
+{
+       return msi_domain_alloc_irq_at(&dev->dev, MSI_SECONDARY_DOMAIN, MSI_ANY_INDEX,
+                                      affdesc, icookie);
+}
+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 <= 0))
+               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
index 1592b630d919aa8ef2789422200d7dbf16e364b5..aa514b54c6818fb8ae2aa3936f8785a35b330b1d 100644 (file)
@@ -2491,6 +2491,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_instance_cookie *icookie,
+                                const struct irq_affinity_desc *affdesc);
+void pci_ims_free_irq(struct pci_dev *pdev, struct msi_map map);
 
 #include <linux/dma-mapping.h>