]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqbypass: Require producers to pass in Linux IRQ number during registration
authorSean Christopherson <seanjc@google.com>
Fri, 16 May 2025 23:07:34 +0000 (16:07 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 20 Jun 2025 20:52:41 +0000 (13:52 -0700)
Pass in the Linux IRQ associated with an IRQ bypass producer instead of
relying on the caller to set the field prior to registration, as there's
no benefit to relying on callers to do the right thing.

Take care to set producer->irq before __connect(), as KVM expects the IRQ
to be valid as soon as a connection is possible.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Link: https://lore.kernel.org/r/20250516230734.2564775-9-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vhost/vdpa.c
include/linux/irqbypass.h
virt/lib/irqbypass.c

index d87fe116762a3e2adc8eb612093fd125b2fa1641..123298a4dc8f51d669cf85e50b987ed6a19de1ad 100644 (file)
@@ -505,8 +505,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
        if (ret)
                goto out_put_eventfd_ctx;
 
-       ctx->producer.irq = irq;
-       ret = irq_bypass_register_producer(&ctx->producer, trigger);
+       ret = irq_bypass_register_producer(&ctx->producer, trigger, irq);
        if (unlikely(ret)) {
                dev_info(&pdev->dev,
                "irq bypass producer (eventfd %p) registration fails: %d\n",
index 7b265ffda6970b553deee15371587d0e7ade2460..af1e1fdfd9ed0b7fa050b872ec34138c8fdb0bfa 100644 (file)
@@ -212,8 +212,8 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid)
        if (!vq->call_ctx.ctx)
                return;
 
-       vq->call_ctx.producer.irq = irq;
-       ret = irq_bypass_register_producer(&vq->call_ctx.producer, vq->call_ctx.ctx);
+       ret = irq_bypass_register_producer(&vq->call_ctx.producer,
+                                          vq->call_ctx.ctx, irq);
        if (unlikely(ret))
                dev_info(&v->dev, "vq %u, irq bypass producer (eventfd %p) registration fails, ret =  %d\n",
                         qid, vq->call_ctx.ctx, ret);
index cd64fcaa88fe68d74a1778c33b6641c0c6e70b29..ede1fa938152f8dc75a302b24a52275f18a7c00e 100644 (file)
@@ -84,7 +84,7 @@ struct irq_bypass_consumer {
 };
 
 int irq_bypass_register_producer(struct irq_bypass_producer *producer,
-                                struct eventfd_ctx *eventfd);
+                                struct eventfd_ctx *eventfd, int irq);
 void irq_bypass_unregister_producer(struct irq_bypass_producer *producer);
 int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer,
                                 struct eventfd_ctx *eventfd);
index ea888b9203d26e5d63ab39219ab4caed110bbb85..62c160200be96f66ab1398981e3918014db64132 100644 (file)
@@ -85,12 +85,13 @@ static void __disconnect(struct irq_bypass_producer *prod,
  * irq_bypass_register_producer - register IRQ bypass producer
  * @producer: pointer to producer structure
  * @eventfd: pointer to the eventfd context associated with the producer
+ * @irq: Linux IRQ number of the underlying producer device
  *
  * Add the provided IRQ producer to the set of producers and connect with the
  * consumer with a matching eventfd, if one exists.
  */
 int irq_bypass_register_producer(struct irq_bypass_producer *producer,
-                                struct eventfd_ctx *eventfd)
+                                struct eventfd_ctx *eventfd, int irq)
 {
        unsigned long index = (unsigned long)eventfd;
        struct irq_bypass_consumer *consumer;
@@ -99,6 +100,8 @@ int irq_bypass_register_producer(struct irq_bypass_producer *producer,
        if (WARN_ON_ONCE(producer->eventfd))
                return -EINVAL;
 
+       producer->irq = irq;
+
        guard(mutex)(&lock);
 
        ret = xa_insert(&producers, index, producer, GFP_KERNEL);