virt/lib/irqbypass.c

Source file repositories/reference/linux-study-clean/virt/lib/irqbypass.c

File Facts

System
Linux kernel
Corpus path
virt/lib/irqbypass.c
Extension
.c
Size
5465 bytes
Lines
215
Domain
Kernel Services
Bucket
virt
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret) {
			WARN_ON_ONCE(xa_erase(&producers, index) != producer);
			return ret;
		}
	}

	producer->eventfd = eventfd;
	return 0;
}
EXPORT_SYMBOL_GPL(irq_bypass_register_producer);

/**
 * irq_bypass_unregister_producer - unregister IRQ bypass producer
 * @producer: pointer to producer structure
 *
 * Remove a previously registered IRQ producer (note, it's safe to call this
 * even if registration was unsuccessful).  Disconnect from the associated
 * consumer, if one exists.
 */
void irq_bypass_unregister_producer(struct irq_bypass_producer *producer)
{
	unsigned long index = (unsigned long)producer->eventfd;

	if (!producer->eventfd)
		return;

	guard(mutex)(&lock);

	if (producer->consumer)
		__disconnect(producer, producer->consumer);

	WARN_ON_ONCE(xa_erase(&producers, index) != producer);
	producer->eventfd = NULL;
}
EXPORT_SYMBOL_GPL(irq_bypass_unregister_producer);

/**
 * irq_bypass_register_consumer - register IRQ bypass consumer
 * @consumer: pointer to consumer structure
 * @eventfd: pointer to the eventfd context associated with the consumer
 *
 * Add the provided IRQ consumer to the set of consumers and connect with the
 * producer with a matching eventfd, if one exists.
 */
int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer,
				 struct eventfd_ctx *eventfd)
{
	unsigned long index = (unsigned long)eventfd;
	struct irq_bypass_producer *producer;
	int ret;

	if (WARN_ON_ONCE(consumer->eventfd))
		return -EINVAL;

	if (!consumer->add_producer || !consumer->del_producer)
		return -EINVAL;

	guard(mutex)(&lock);

	ret = xa_insert(&consumers, index, consumer, GFP_KERNEL);
	if (ret)
		return ret;

	producer = xa_load(&producers, index);
	if (producer) {
		ret = __connect(producer, consumer);
		if (ret) {
			WARN_ON_ONCE(xa_erase(&consumers, index) != consumer);
			return ret;
		}
	}

	consumer->eventfd = eventfd;
	return 0;
}
EXPORT_SYMBOL_GPL(irq_bypass_register_consumer);

/**
 * irq_bypass_unregister_consumer - unregister IRQ bypass consumer
 * @consumer: pointer to consumer structure
 *
 * Remove a previously registered IRQ consumer (note, it's safe to call this
 * even if registration was unsuccessful).  Disconnect from the associated
 * producer, if one exists.
 */
void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer)
{
	unsigned long index = (unsigned long)consumer->eventfd;

	if (!consumer->eventfd)

Annotation

Implementation Notes