linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Joerg Roedel <joro@8bytes.org>,
	Will Deacon <will@kernel.org>,
	linux-pci@vger.kernel.org, Bjorn Helgaas <bhelgaas@google.com>,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Marc Zyngier <maz@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	Dave Jiang <dave.jiang@intel.com>,
	Alex Williamson <alex.williamson@redhat.com>,
	Kevin Tian <kevin.tian@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	Logan Gunthorpe <logang@deltatee.com>,
	Ashok Raj <ashok.raj@intel.com>, Jon Mason <jdmason@kudzu.us>,
	Allen Hubbe <allenbh@gmail.com>
Subject: [patch V3 21/33] genirq/msi: Provide msi_domain_alloc_irq_at()
Date: Fri, 25 Nov 2022 00:26:18 +0100 (CET)	[thread overview]
Message-ID: <20221124232326.501359457@linutronix.de> (raw)
In-Reply-To: 20221124230505.073418677@linutronix.de

For supporting post MSI-X enable allocations and for the upcoming PCI/IMS
support a separate interface is required which allows not only the
allocation of a specific index, but also the allocation of any, i.e. the
next free index. The latter is especially required for IMS because IMS
completely does away with index to functionality mappings which are
often found in MSI/MSI-X implementation.

But even with MSI-X there are devices where only the first few indices have
a fixed functionality and the rest is freely assignable by software,
e.g. to queues.

msi_domain_alloc_irq_at() is also different from the range based interfaces
as it always enforces that the MSI descriptor is allocated by the core code
and not preallocated by the caller like the PCI/MSI[-X] enable code path
does.

msi_domain_alloc_irq_at() can be invoked with the index argument set to
MSI_ANY_INDEX which makes the core code pick the next free index. The irq
domain can provide a prepare_desc() operation callback in it's
msi_domain_ops to do domain specific post allocation initialization before
the actual Linux interrupt and the associated interrupt descriptor and
hierarchy alloccations are conducted.

The function also takes an optional @icookie argument which is of type
union msi_instance_cookie. This cookie is not used by the core code and is
stored in the allocated msi_desc::data::icookie. The meaning of the cookie
is completely implementation defined. In case of IMS this might be a PASID
or a pointer to a device queue, but for the MSI core it's opaque and not
used in any way.

The function returns a struct msi_map which on success contains the
allocated index number and the Linux interrupt number so the caller can
spare the index to Linux interrupt number lookup.

On failure map::index contains the error code and map::virq is 0.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Fix the recursive allocation issue and the index calculation (Reinette)
V3: Fixup stale changelog and typos in comments (Kevin)
    Adopt to the reworked domain/xarray storage model
---
 include/linux/msi.h     |    4 +
 include/linux/msi_api.h |    7 +++
 kernel/irq/msi.c        |  107 +++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 108 insertions(+), 10 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -80,6 +80,7 @@ struct pci_dev;
 struct platform_msi_priv_data;
 struct device_attribute;
 struct irq_domain;
+struct irq_affinity_desc;
 
 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 #ifdef CONFIG_GENERIC_MSI_IRQ
@@ -602,6 +603,9 @@ int msi_domain_alloc_irqs_range(struct d
 				unsigned int first, unsigned int last);
 int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int nirqs);
 
+struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index,
+				       const struct irq_affinity_desc *affdesc,
+				       union msi_instance_cookie *cookie);
 
 void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid,
 				       unsigned int first, unsigned int last);
--- a/include/linux/msi_api.h
+++ b/include/linux/msi_api.h
@@ -48,6 +48,13 @@ struct msi_map {
 	int	virq;
 };
 
+/*
+ * Constant to be used for dynamic allocations when the allocation is any
+ * free MSI index, which is either an entry in a hardware table or a
+ * software managed index.
+ */
+#define MSI_ANY_INDEX		UINT_MAX
+
 unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index);
 
 /**
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -90,17 +90,30 @@ static int msi_insert_desc(struct device
 	int ret;
 
 	hwsize = msi_domain_get_hwsize(dev, domid);
-	if (index >= hwsize) {
-		ret = -ERANGE;
-		goto fail;
-	}
 
-	desc->msi_index = index;
-	ret = xa_insert(xa, index, desc, GFP_KERNEL);
-	if (ret)
-		goto fail;
-	return 0;
+	if (index == MSI_ANY_INDEX) {
+		struct xa_limit limit = { .min = 0, .max = hwsize - 1 };
+		unsigned int index;
+
+		/* Let the xarray allocate a free index within the limit */
+		ret = xa_alloc(xa, &index, desc, limit, GFP_KERNEL);
+		if (ret)
+			goto fail;
 
+		desc->msi_index = index;
+		return 0;
+	} else {
+		if (index >= hwsize) {
+			ret = -ERANGE;
+			goto fail;
+		}
+
+		desc->msi_index = index;
+		ret = xa_insert(xa, index, desc, GFP_KERNEL);
+		if (ret)
+			goto fail;
+		return 0;
+	}
 fail:
 	msi_free_desc(desc);
 	return ret;
@@ -294,7 +307,7 @@ int msi_setup_device_data(struct device
 	}
 
 	for (i = 0; i < MSI_MAX_DEVICE_IRQDOMAINS; i++)
-		xa_init(&md->__domains[i].store);
+		xa_init_flags(&md->__domains[i].store, XA_FLAGS_ALLOC);
 
 	/*
 	 * If @dev::msi::domain is set and is a global MSI domain, copy the
@@ -1407,6 +1420,80 @@ int msi_domain_alloc_irqs_all_locked(str
 	return msi_domain_alloc_locked(dev, &ctrl);
 }
 
+/**
+ * msi_domain_alloc_irq_at - Allocate an interrupt from a MSI interrupt domain at
+ *			     a given index - or at the next free index
+ *
+ * @dev:	Pointer to device struct of the device for which the interrupts
+ *		are allocated
+ * @domid:	Id of the interrupt domain to operate on
+ * @index:	Index for allocation. If @index == %MSI_ANY_INDEX the allocation
+ *		uses the next free index.
+ * @affdesc:	Optional pointer to an interrupt affinity descriptor structure
+ * @icookie:	Optional pointer to a domain specific per instance cookie. If
+ *		non-NULL the content of the cookie is stored in msi_desc::data.
+ *		Must be NULL for MSI-X allocations
+ *
+ * This requires a MSI interrupt domain which lets the core code manage the
+ * MSI descriptors.
+ *
+ * Return: struct msi_map
+ *
+ *	On success msi_map::index contains the allocated index number and
+ *	msi_map::virq the corresponding Linux interrupt number
+ *
+ *	On failure msi_map::index contains the error code and msi_map::virq
+ *	is %0.
+ */
+struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index,
+				       const struct irq_affinity_desc *affdesc,
+				       union msi_instance_cookie *icookie)
+{
+	struct msi_ctrl ctrl = { .domid	= domid, .nirqs = 1, };
+	struct msi_domain_info *info;
+	struct irq_domain *domain;
+	struct msi_map map = { };
+	struct msi_desc *desc;
+	int ret;
+
+	msi_lock_descs(dev);
+	domain = msi_get_device_domain(dev, domid);
+	if (!domain) {
+		map.index = -ENODEV;
+		goto unlock;
+	}
+
+	desc = msi_alloc_desc(dev, 1, affdesc);
+	if (!desc) {
+		map.index = -ENOMEM;
+		goto unlock;
+	}
+
+	if (icookie)
+		desc->data.icookie = *icookie;
+
+	ret = msi_insert_desc(dev, desc, domid, index);
+	if (ret) {
+		map.index = ret;
+		goto unlock;
+	}
+
+	ctrl.first = ctrl.last = desc->msi_index;
+	info = domain->host_data;
+
+	ret = __msi_domain_alloc_irqs(dev, domain, &ctrl);
+	if (ret) {
+		map.index = ret;
+		msi_domain_free_locked(dev, &ctrl);
+	} else {
+		map.index = desc->msi_index;
+		map.virq = desc->irq;
+	}
+unlock:
+	msi_unlock_descs(dev);
+	return map;
+}
+
 static void __msi_domain_free_irqs(struct device *dev, struct irq_domain *domain,
 				   struct msi_ctrl *ctrl)
 {


  parent reply	other threads:[~2022-11-24 23:30 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-24 23:25 [patch V3 00/33] genirq, PCI/MSI: Support for per device MSI and PCI/IMS - Part 3 implementation Thomas Gleixner
2022-11-24 23:25 ` [patch V3 01/33] genirq/msi: Rearrange MSI domain flags Thomas Gleixner
2022-11-24 23:25 ` [patch V3 02/33] genirq/msi: Provide struct msi_parent_ops Thomas Gleixner
2022-11-24 23:25 ` [patch V3 03/33] genirq/msi: Provide data structs for per device domains Thomas Gleixner
2022-11-24 23:25 ` [patch V3 04/33] genirq/msi: Add size info to struct msi_domain_info Thomas Gleixner
2022-11-24 23:25 ` [patch V3 05/33] genirq/msi: Split msi_create_irq_domain() Thomas Gleixner
2022-11-24 23:25 ` [patch V3 06/33] genirq/irqdomain: Add irq_domain::dev for per device MSI domains Thomas Gleixner
2022-11-24 23:25 ` [patch V3 07/33] genirq/msi: Provide msi_create/free_device_irq_domain() Thomas Gleixner
2022-11-24 23:25 ` [patch V3 08/33] genirq/msi: Provide msi_match_device_domain() Thomas Gleixner
2022-11-24 23:25 ` [patch V3 09/33] genirq/msi: Add range checking to msi_insert_desc() Thomas Gleixner
2022-12-13 19:04   ` Guenter Roeck
2022-12-14  9:42     ` Niklas Schnelle
2022-12-15 14:49       ` Thomas Gleixner
2022-12-15 16:23         ` Matthew Rosato
2022-12-15 21:32           ` Guenter Roeck
2022-12-16  9:53           ` Marc Zyngier
2022-12-16 13:50             ` Matthew Rosato
2022-12-16 13:58               ` Marc Zyngier
2022-12-16 14:03                 ` Marc Zyngier
2022-12-16 14:11                   ` Matthew Rosato
2022-12-16 17:30                     ` Marc Zyngier
2022-12-16 15:47                 ` Guenter Roeck
2022-12-17  0:45                 ` Guenter Roeck
2022-12-17 10:46                   ` Marc Zyngier
2022-12-17 13:36                     ` Guenter Roeck
2023-02-20 17:11   ` [REGRESSION] " Russell King (Oracle)
2023-02-20 18:29     ` Marc Zyngier
2023-02-20 18:43       ` Thomas Gleixner
2023-02-20 19:00       ` Russell King (Oracle)
2023-02-20 19:17       ` Russell King (Oracle)
2023-02-20 19:43         ` Andrew Lunn
2023-02-20 18:30     ` Thomas Gleixner
2022-11-24 23:26 ` [patch V3 10/33] PCI/MSI: Split __pci_write_msi_msg() Thomas Gleixner
2022-11-24 23:26 ` [patch V3 11/33] genirq/msi: Provide BUS_DEVICE_PCI_MSI[X] Thomas Gleixner
2022-11-24 23:26 ` [patch V3 12/33] PCI/MSI: Add support for per device MSI[X] domains Thomas Gleixner
2022-11-28  4:46   ` Tian, Kevin
2022-11-24 23:26 ` [patch V3 13/33] x86/apic/vector: Provide MSI parent domain Thomas Gleixner
2023-01-04 12:34   ` Jason Gunthorpe
2023-01-09 20:32     ` Thomas Gleixner
2023-01-10 12:14     ` Thomas Gleixner
2023-01-10 14:59       ` Jason Gunthorpe
2023-01-11 16:02         ` Kalle Valo
2023-01-11 16:35           ` Jason Gunthorpe
2023-01-11 17:07             ` Kalle Valo
2022-11-24 23:26 ` [patch V3 14/33] PCI/MSI: Remove unused pci_dev_has_special_msi_domain() Thomas Gleixner
2022-11-24 23:26 ` [patch V3 15/33] iommu/vt-d: Switch to MSI parent domains Thomas Gleixner
2022-11-24 23:26 ` [patch V3 16/33] iommu/amd: Switch to MSI base domains Thomas Gleixner
2022-11-24 23:26 ` [patch V3 17/33] x86/apic/msi: Remove arch_create_remap_msi_irq_domain() Thomas Gleixner
2022-11-24 23:26 ` [patch V3 18/33] genirq/msi: Provide struct msi_map Thomas Gleixner
2022-11-24 23:26 ` [patch V3 19/33] genirq/msi: Provide msi_desc::msi_data Thomas Gleixner
2022-11-24 23:26 ` [patch V3 20/33] genirq/msi: Provide msi_domain_ops::prepare_desc() Thomas Gleixner
2022-11-24 23:26 ` Thomas Gleixner [this message]
2022-11-24 23:26 ` [patch V3 22/33] genirq/msi: Provide MSI_FLAG_MSIX_ALLOC_DYN Thomas Gleixner
2022-11-24 23:26 ` [patch V3 23/33] PCI/MSI: Split MSI-X descriptor setup Thomas Gleixner
2022-11-24 23:26 ` [patch V3 24/33] PCI/MSI: Provide prepare_desc() MSI domain op Thomas Gleixner
2022-11-24 23:26 ` [patch V3 25/33] PCI/MSI: Provide post-enable dynamic allocation interfaces for MSI-X Thomas Gleixner
2022-11-24 23:26 ` [patch V3 26/33] x86/apic/msi: Enable MSI_FLAG_PCI_MSIX_ALLOC_DYN Thomas Gleixner
2022-11-24 23:26 ` [patch V3 27/33] genirq/msi: Provide constants for PCI/IMS support Thomas Gleixner
2022-11-24 23:26 ` [patch V3 28/33] PCI/MSI: Provide IMS (Interrupt Message Store) support Thomas Gleixner
2024-03-27 16:32   ` Bjorn Helgaas
2024-03-29  1:41     ` Tian, Kevin
2022-11-24 23:26 ` [patch V3 29/33] PCI/MSI: Provide pci_ims_alloc/free_irq() Thomas Gleixner
2022-11-28  4:47   ` Tian, Kevin
2022-11-24 23:26 ` [patch V3 30/33] x86/apic/msi: Enable PCI/IMS Thomas Gleixner
2022-11-24 23:26 ` [patch V3 31/33] iommu/vt-d: " Thomas Gleixner
2022-11-24 23:26 ` [patch V3 32/33] iommu/amd: " Thomas Gleixner
2022-11-24 23:26 ` [patch V3 33/33] irqchip: Add IDXD Interrupt Message Store driver Thomas Gleixner
2022-11-28  4:50 ` [patch V3 00/33] genirq, PCI/MSI: Support for per device MSI and PCI/IMS - Part 3 implementation Tian, Kevin
2022-12-05 11:07 ` Marc Zyngier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221124232326.501359457@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=alex.williamson@redhat.com \
    --cc=allenbh@gmail.com \
    --cc=ashok.raj@intel.com \
    --cc=bhelgaas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jdmason@kudzu.us \
    --cc=jgg@mellanox.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=maz@kernel.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).