Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqbypass: Require producers to pass in Linux IRQ number during registration

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>

+8 -6
+1 -2
drivers/vfio/pci/vfio_pci_intrs.c
··· 505 505 if (ret) 506 506 goto out_put_eventfd_ctx; 507 507 508 - ctx->producer.irq = irq; 509 - ret = irq_bypass_register_producer(&ctx->producer, trigger); 508 + ret = irq_bypass_register_producer(&ctx->producer, trigger, irq); 510 509 if (unlikely(ret)) { 511 510 dev_info(&pdev->dev, 512 511 "irq bypass producer (eventfd %p) registration fails: %d\n",
+2 -2
drivers/vhost/vdpa.c
··· 212 212 if (!vq->call_ctx.ctx) 213 213 return; 214 214 215 - vq->call_ctx.producer.irq = irq; 216 - ret = irq_bypass_register_producer(&vq->call_ctx.producer, vq->call_ctx.ctx); 215 + ret = irq_bypass_register_producer(&vq->call_ctx.producer, 216 + vq->call_ctx.ctx, irq); 217 217 if (unlikely(ret)) 218 218 dev_info(&v->dev, "vq %u, irq bypass producer (eventfd %p) registration fails, ret = %d\n", 219 219 qid, vq->call_ctx.ctx, ret);
+1 -1
include/linux/irqbypass.h
··· 84 84 }; 85 85 86 86 int irq_bypass_register_producer(struct irq_bypass_producer *producer, 87 - struct eventfd_ctx *eventfd); 87 + struct eventfd_ctx *eventfd, int irq); 88 88 void irq_bypass_unregister_producer(struct irq_bypass_producer *producer); 89 89 int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer, 90 90 struct eventfd_ctx *eventfd);
+4 -1
virt/lib/irqbypass.c
··· 85 85 * irq_bypass_register_producer - register IRQ bypass producer 86 86 * @producer: pointer to producer structure 87 87 * @eventfd: pointer to the eventfd context associated with the producer 88 + * @irq: Linux IRQ number of the underlying producer device 88 89 * 89 90 * Add the provided IRQ producer to the set of producers and connect with the 90 91 * consumer with a matching eventfd, if one exists. 91 92 */ 92 93 int irq_bypass_register_producer(struct irq_bypass_producer *producer, 93 - struct eventfd_ctx *eventfd) 94 + struct eventfd_ctx *eventfd, int irq) 94 95 { 95 96 unsigned long index = (unsigned long)eventfd; 96 97 struct irq_bypass_consumer *consumer; ··· 99 98 100 99 if (WARN_ON_ONCE(producer->eventfd)) 101 100 return -EINVAL; 101 + 102 + producer->irq = irq; 102 103 103 104 guard(mutex)(&lock); 104 105