Skip to content

Commit add57f4

Browse files
committed
irqbypass: Explicitly track producer and consumer bindings
Explicitly track IRQ bypass producer:consumer bindings. This will allow making removal an O(1) operation; searching through the list to find information that is trivially tracked (and useful for debug) is wasteful. Reviewed-by: Kevin Tian <kevin.tian@intel.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Link: https://lore.kernel.org/r/20250516230734.2564775-5-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 2b521d8 commit add57f4

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

include/linux/irqbypass.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ struct irq_bypass_consumer;
2929
* pairings are not supported.
3030
*/
3131

32+
struct irq_bypass_consumer;
33+
3234
/**
3335
* struct irq_bypass_producer - IRQ bypass producer definition
3436
* @node: IRQ bypass manager private list management
3537
* @eventfd: eventfd context used to match producers and consumers
38+
* @consumer: The connected consumer (NULL if no connection)
3639
* @irq: Linux IRQ number for the producer device
3740
* @add_consumer: Connect the IRQ producer to an IRQ consumer (optional)
3841
* @del_consumer: Disconnect the IRQ producer from an IRQ consumer (optional)
@@ -46,6 +49,7 @@ struct irq_bypass_consumer;
4649
struct irq_bypass_producer {
4750
struct list_head node;
4851
struct eventfd_ctx *eventfd;
52+
struct irq_bypass_consumer *consumer;
4953
int irq;
5054
int (*add_consumer)(struct irq_bypass_producer *,
5155
struct irq_bypass_consumer *);
@@ -59,6 +63,7 @@ struct irq_bypass_producer {
5963
* struct irq_bypass_consumer - IRQ bypass consumer definition
6064
* @node: IRQ bypass manager private list management
6165
* @eventfd: eventfd context used to match producers and consumers
66+
* @producer: The connected producer (NULL if no connection)
6267
* @add_producer: Connect the IRQ consumer to an IRQ producer
6368
* @del_producer: Disconnect the IRQ consumer from an IRQ producer
6469
* @stop: Perform any quiesce operations necessary prior to add/del (optional)
@@ -72,6 +77,8 @@ struct irq_bypass_producer {
7277
struct irq_bypass_consumer {
7378
struct list_head node;
7479
struct eventfd_ctx *eventfd;
80+
struct irq_bypass_producer *producer;
81+
7582
int (*add_producer)(struct irq_bypass_consumer *,
7683
struct irq_bypass_producer *);
7784
void (*del_producer)(struct irq_bypass_consumer *,

virt/lib/irqbypass.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ static int __connect(struct irq_bypass_producer *prod,
5151
if (prod->start)
5252
prod->start(prod);
5353

54+
if (!ret) {
55+
prod->consumer = cons;
56+
cons->producer = prod;
57+
}
5458
return ret;
5559
}
5660

@@ -72,6 +76,9 @@ static void __disconnect(struct irq_bypass_producer *prod,
7276
cons->start(cons);
7377
if (prod->start)
7478
prod->start(prod);
79+
80+
prod->consumer = NULL;
81+
cons->producer = NULL;
7582
}
7683

7784
/**
@@ -145,6 +152,7 @@ void irq_bypass_unregister_producer(struct irq_bypass_producer *producer)
145152

146153
list_for_each_entry(consumer, &consumers, node) {
147154
if (consumer->eventfd == producer->eventfd) {
155+
WARN_ON_ONCE(producer->consumer != consumer);
148156
__disconnect(producer, consumer);
149157
break;
150158
}
@@ -234,6 +242,7 @@ void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer)
234242

235243
list_for_each_entry(producer, &producers, node) {
236244
if (producer->eventfd == consumer->eventfd) {
245+
WARN_ON_ONCE(consumer->producer != producer);
237246
__disconnect(producer, consumer);
238247
break;
239248
}

0 commit comments

Comments
 (0)