cregit-Linux how code gets into the kernel

Release 4.15 virt/lib/irqbypass.c

Directory: virt/lib
/*
 * IRQ offload/bypass manager
 *
 * Copyright (C) 2015 Red Hat, Inc.
 * Copyright (c) 2015 Linaro Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Various virtualization hardware acceleration techniques allow bypassing or
 * offloading interrupts received from devices around the host kernel.  Posted
 * Interrupts on Intel VT-d systems can allow interrupts to be received
 * directly by a virtual machine.  ARM IRQ Forwarding allows forwarded physical
 * interrupts to be directly deactivated by the guest.  This manager allows
 * interrupt producers and consumers to find each other to enable this sort of
 * bypass.
 */

#include <linux/irqbypass.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("IRQ bypass manager utility module");

static LIST_HEAD(producers);
static LIST_HEAD(consumers);
static DEFINE_MUTEX(lock);

/* @lock must be held when calling connect */

static int __connect(struct irq_bypass_producer *prod, struct irq_bypass_consumer *cons) { int ret = 0; if (prod->stop) prod->stop(prod); if (cons->stop) cons->stop(cons); if (prod->add_consumer) ret = prod->add_consumer(prod, cons); if (!ret) { ret = cons->add_producer(cons, prod); if (ret && prod->del_consumer) prod->del_consumer(prod, cons); } if (cons->start) cons->start(cons); if (prod->start) prod->start(prod); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson128100.00%1100.00%
Total128100.00%1100.00%

/* @lock must be held when calling disconnect */
static void __disconnect(struct irq_bypass_producer *prod, struct irq_bypass_consumer *cons) { if (prod->stop) prod->stop(prod); if (cons->stop) cons->stop(cons); cons->del_producer(cons, prod); if (prod->del_consumer) prod->del_consumer(prod, cons); if (cons->start) cons->start(cons); if (prod->start) prod->start(prod); }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson92100.00%1100.00%
Total92100.00%1100.00%

/** * irq_bypass_register_producer - register IRQ bypass producer * @producer: pointer to producer structure * * Add the provided IRQ producer to the list of producers and connect * with any matching token found on the IRQ consumers list. */
int irq_bypass_register_producer(struct irq_bypass_producer *producer) { struct irq_bypass_producer *tmp; struct irq_bypass_consumer *consumer; if (!producer->token) return -EINVAL; might_sleep(); if (!try_module_get(THIS_MODULE)) return -ENODEV; mutex_lock(&lock); list_for_each_entry(tmp, &producers, node) { if (tmp->token == producer->token) { mutex_unlock(&lock); module_put(THIS_MODULE); return -EBUSY; } } list_for_each_entry(consumer, &consumers, node) { if (consumer->token == producer->token) { int ret = __connect(producer, consumer); if (ret) { mutex_unlock(&lock); module_put(THIS_MODULE); return ret; } break; } } list_add(&producer->node, &producers); mutex_unlock(&lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson162100.00%2100.00%
Total162100.00%2100.00%

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 from the list of producers * and disconnect it from any connected IRQ consumer. */
void irq_bypass_unregister_producer(struct irq_bypass_producer *producer) { struct irq_bypass_producer *tmp; struct irq_bypass_consumer *consumer; if (!producer->token) return; might_sleep(); if (!try_module_get(THIS_MODULE)) return; /* nothing in the list anyway */ mutex_lock(&lock); list_for_each_entry(tmp, &producers, node) { if (tmp->token != producer->token) continue; list_for_each_entry(consumer, &consumers, node) { if (consumer->token == producer->token) { __disconnect(producer, consumer); break; } } list_del(&producer->node); module_put(THIS_MODULE); break; } mutex_unlock(&lock); module_put(THIS_MODULE); }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson123100.00%2100.00%
Total123100.00%2100.00%

EXPORT_SYMBOL_GPL(irq_bypass_unregister_producer); /** * irq_bypass_register_consumer - register IRQ bypass consumer * @consumer: pointer to consumer structure * * Add the provided IRQ consumer to the list of consumers and connect * with any matching token found on the IRQ producer list. */
int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer) { struct irq_bypass_consumer *tmp; struct irq_bypass_producer *producer; if (!consumer->token || !consumer->add_producer || !consumer->del_producer) return -EINVAL; might_sleep(); if (!try_module_get(THIS_MODULE)) return -ENODEV; mutex_lock(&lock); list_for_each_entry(tmp, &consumers, node) { if (tmp->token == consumer->token || tmp == consumer) { mutex_unlock(&lock); module_put(THIS_MODULE); return -EBUSY; } } list_for_each_entry(producer, &producers, node) { if (producer->token == consumer->token) { int ret = __connect(producer, consumer); if (ret) { mutex_unlock(&lock); module_put(THIS_MODULE); return ret; } break; } } list_add(&consumer->node, &consumers); mutex_unlock(&lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson17297.73%266.67%
Wanpeng Li42.27%133.33%
Total176100.00%3100.00%

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 from the list of consumers * and disconnect it from any connected IRQ producer. */
void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer) { struct irq_bypass_consumer *tmp; struct irq_bypass_producer *producer; if (!consumer->token) return; might_sleep(); if (!try_module_get(THIS_MODULE)) return; /* nothing in the list anyway */ mutex_lock(&lock); list_for_each_entry(tmp, &consumers, node) { if (tmp != consumer) continue; list_for_each_entry(producer, &producers, node) { if (producer->token == consumer->token) { __disconnect(producer, consumer); break; } } list_del(&consumer->node); module_put(THIS_MODULE); break; } mutex_unlock(&lock); module_put(THIS_MODULE); }

Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson119100.00%2100.00%
Total119100.00%2100.00%

EXPORT_SYMBOL_GPL(irq_bypass_unregister_consumer);

Overall Contributors

PersonTokensPropCommitsCommitProp
Alex Williamson86399.54%266.67%
Wanpeng Li40.46%133.33%
Total867100.00%3100.00%
Directory: virt/lib
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.