Thread (64 messages) 64 messages, 6 authors, 2021-06-11

Re: [PATCH v6 05/20] vfio: mdev: common lib code for setting up Interrupt Message Store

From: Jason Gunthorpe <jgg@nvidia.com>
Date: 2021-05-24 00:03:04
Also in: dmaengine, lkml

On Fri, May 21, 2021 at 05:19:36PM -0700, Dave Jiang wrote:
Add common helper code to setup IMS once the MSI domain has been
setup by the device driver. The main helper function is
mdev_ims_set_msix_trigger() that is called by the VFIO ioctl
VFIO_DEVICE_SET_IRQS. The function deals with the setup and
teardown of emulated and IMS backed eventfd that gets exported
to the guest kernel via VFIO as MSIX vectors.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/vfio/mdev/Kconfig     |   12 ++
 drivers/vfio/mdev/Makefile    |    3 
 drivers/vfio/mdev/mdev_irqs.c |  318 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mdev.h          |   51 +++++++
 4 files changed, 384 insertions(+)
 create mode 100644 drivers/vfio/mdev/mdev_irqs.c
IMS is not mdev specific, do not entangle it with mdev code. This
should be generic VFIO stuff.
+static int mdev_msix_set_vector_signal(struct mdev_irq *mdev_irq, int vector, int fd)
+{
+	int rc, irq;
+	struct mdev_device *mdev = irq_to_mdev(mdev_irq);
+	struct mdev_irq_entry *entry;
+	struct device *dev = &mdev->dev;
+	struct eventfd_ctx *trigger;
+	char *name;
+	bool pasid_en;
+	u32 auxval;
+
+	if (vector < 0 || vector >= mdev_irq->num)
+		return -EINVAL;
+
+	entry = &mdev_irq->irq_entries[vector];
+
+	if (entry->ims)
+		irq = dev_msi_irq_vector(dev, entry->ims_id);
+	else
+		irq = 0;
+
+	pasid_en = mdev_irq->pasid != INVALID_IOASID ? true : false;
+
+	/* IMS and invalid pasid is not a valid configuration */
+	if (entry->ims && !pasid_en)
+		return -EINVAL;
+
+	if (entry->trigger) {
+		if (irq) {
+			irq_bypass_unregister_producer(&entry->producer);
+			free_irq(irq, entry->trigger);
+			if (pasid_en) {
+				auxval = ims_ctrl_pasid_aux(0, false);
+				irq_set_auxdata(irq, IMS_AUXDATA_CONTROL_WORD, auxval);
+			}
+		}
+		kfree(entry->name);
+		eventfd_ctx_put(entry->trigger);
+		entry->trigger = NULL;
+	}
+
+	if (fd < 0)
+		return 0;
+
+	name = kasprintf(GFP_KERNEL, "vfio-mdev-irq[%d](%s)", vector, dev_name(dev));
+	if (!name)
+		return -ENOMEM;
+
+	trigger = eventfd_ctx_fdget(fd);
+	if (IS_ERR(trigger)) {
+		kfree(name);
+		return PTR_ERR(trigger);
+	}
+
+	entry->name = name;
+	entry->trigger = trigger;
+
+	if (!irq)
+		return 0;
+
+	if (pasid_en) {
+		auxval = ims_ctrl_pasid_aux(mdev_irq->pasid, true);
+		rc = irq_set_auxdata(irq, IMS_AUXDATA_CONTROL_WORD, auxval);
+		if (rc < 0)
+			goto err;
Why is anything to do with PASID here? Something has gone wrong with
the layers I suspect..

Oh yes. drivers/irqchip/irq-ims-msi.c is dxd specific and shouldn't be
pretending to be common code.

The protocol to stuff the pasid and other stuff into the auxdata is
also compeltely idxd specific and is just a hacky way to communicate
from this code to the IDXD irq-chip.

So this doesn't belong here either. Pass in the auxdata from the idxd
code and I'd rename the irq-ims-msi to irq-ims-idxd
+static int mdev_msix_enable(struct mdev_irq *mdev_irq, int nvec)
+{
+	struct mdev_device *mdev = irq_to_mdev(mdev_irq);
+	struct device *dev;
+	int rc;
+
+	if (nvec != mdev_irq->num)
+		return -EINVAL;
+
+	if (mdev_irq->ims_num) {
+		dev = &mdev->dev;
+		rc = msi_domain_alloc_irqs(dev_get_msi_domain(dev), dev, mdev_irq->ims_num);
Huh? The PCI device should be the only device touching IRQ stuff. I'm
nervous to see you mix in the mdev struct device into this function.

Isn't the msi_domain just idxd->ims_domain?

Jason
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help