Revert irq-forward patches.
Cleaning up v5.4-manatee branch from local fixes, moving all
-manatee specific patches to sys-kernel/chromeos-kernel-5_4-manatee/files
This reverts commit 12854f89b80b4a30759735d82374261f847cb3e5
"irq-forward: use global workqueue to clean up"
This reverts commit ccc2dab144ed2cd2b2ac14b83376d66bd8903112.
"irq-forward: use dynamic dev-minor allocation."
This reverts commit 3111fd8c1bfef469c730d543fa2a0f74100bb3c4.
"irq-forward: experimental interrupt user space forwaring module."
BUG=None
TEST=None
Signed-off-by: Tomasz Jeznach <tjeznach@chromium.org>
Change-Id: Ibe942a37b233be4eec174b364da0c86fc63efe4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2900826
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
diff --git a/include/linux/plat_irqfd.h b/include/linux/plat_irqfd.h
deleted file mode 100644
index e08e516..0000000
--- a/include/linux/plat_irqfd.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright 2020 Google LLC
- */
-
-#ifndef PLAT_IRQFD_H
-#define PLAT_IRQFD_H
-
-#ifdef CONFIG_PLAT_IRQ_FORWARD
-
-struct plat_irq_forward_irqfd {
- struct eventfd_ctx *eventfd;
- int (*handler)(int irq, void *data);
- void *data;
- wait_queue_entry_t wait;
- poll_table pt;
- struct work_struct shutdown;
- struct plat_irq_forward_irqfd **pirqfd;
-};
-
-struct plat_irq_forward_edge_triggered {
- struct eventfd_ctx *trigger;
- uint32_t irq_num;
- struct list_head list;
-};
-
-struct plat_irq_forward_level_triggered {
- struct eventfd_ctx *trigger;
- uint32_t irq_num;
- struct list_head list;
- struct plat_irq_forward_irqfd *unmask;
- bool is_masked;
- spinlock_t spinlock;
-};
-
-int plat_irq_forward_irqfd_enable(int (*handler)(int irq, void *data),
- void *data, struct plat_irq_forward_irqfd **pirqfd, int fd);
-
-#endif /* CONFIG_PLAT_IRQ_FORWARD */
-#endif /* PLAT_IRQFD_H */
diff --git a/include/uapi/linux/platirqforward.h b/include/uapi/linux/platirqforward.h
deleted file mode 100644
index f8a255e..0000000
--- a/include/uapi/linux/platirqforward.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * API definition for Platform IRQ Forwarding to KVM guests
- *
- * 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.
- *
- * Copyright 2020 Google LLC
- *
- */
-#ifndef _UAPI_LINUX_PLATIRQFORWARD_H
-#define _UAPI_LINUX_PLATIRQFORWARD_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define PLAT_IRQ_FORWARD_API_VERSION 0
-
-#define PLAT_IRQ_FORWARD_TYPE (';')
-#define PLAT_IRQ_FORWARD_BASE 100
-
-/**
- *
- * Set masking and unmasking of interrupts. Caller provides
- * struct plat_irq_forward_set with all fields set.
- *
- */
-struct plat_irq_forward_set {
- __u32 argsz;
- __u32 action_flags;
-#define PLAT_IRQ_FORWARD_SET_LEVEL_TRIGGER_EVENTFD (1 << 0)
-#define PLAT_IRQ_FORWARD_SET_LEVEL_UNMASK_EVENTFD (1 << 1)
-#define PLAT_IRQ_FORWARD_SET_EDGE_TRIGGER (1 << 2)
- __u32 irq_number_host;
- __u32 count;
- __u8 eventfd[];
-};
-
-/* ---- IOCTLs for Platform IRQ Forwarding fd (/dev/plat-irq-forward) ---- */
-#define PLAT_IRQ_FORWARD_SET _IO(PLAT_IRQ_FORWARD_TYPE, PLAT_IRQ_FORWARD_BASE)
-
-#endif /* _UAPI_LINUX_PLATIRQFORWARD_H */
diff --git a/virt/lib/Kconfig b/virt/lib/Kconfig
index 68d911e..2d9523b 100644
--- a/virt/lib/Kconfig
+++ b/virt/lib/Kconfig
@@ -1,6 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
config IRQ_BYPASS_MANAGER
tristate
-
-config PLAT_IRQ_FORWARD
- tristate "Enable forwarding arbitrary platform IRQs to guest in KVM"
diff --git a/virt/lib/Makefile b/virt/lib/Makefile
index 633e793..bd7f9a7 100644
--- a/virt/lib/Makefile
+++ b/virt/lib/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_IRQ_BYPASS_MANAGER) += irqbypass.o
-obj-$(CONFIG_PLAT_IRQ_FORWARD) += platirqforward.o plat_irqfd.o
diff --git a/virt/lib/plat_irqfd.c b/virt/lib/plat_irqfd.c
deleted file mode 100644
index 07b24f2..0000000
--- a/virt/lib/plat_irqfd.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Experimental driver for user space interrupt handler.
- *
- * Copyright 2020 Google LLC
- *
- */
-
-#include <linux/file.h>
-#include <linux/vfio.h>
-#include <linux/eventfd.h>
-#include <linux/slab.h>
-#include <uapi/linux/platirqforward.h>
-#include <linux/plat_irqfd.h>
-
-static DEFINE_SPINLOCK(plat_irqfd_lock);
-
-static void plat_irqfd_deactivate(struct plat_irq_forward_irqfd *plat_irqfd)
-{
- schedule_work(&plat_irqfd->shutdown);
-}
-
-static int plat_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode,
- int sync, void *key)
-{
- struct plat_irq_forward_irqfd *plat_irqfd =
- container_of(wait, struct plat_irq_forward_irqfd, wait);
- __poll_t flags = key_to_poll(key);
-
- if (flags & EPOLLIN) {
- /* An event has been signaled, call function */
- if (!plat_irqfd->handler ||
- plat_irqfd->handler(-1, plat_irqfd->data))
- pr_emerg("handler failed\n");
- }
-
- if (flags & EPOLLHUP) {
- unsigned long flags;
-
- spin_lock_irqsave(&plat_irqfd_lock, flags);
-
- /*
- * The eventfd is closing, if the plat_irqfd has not yet been
- * queued for release, as determined by testing whether the
- * plat_irqfd pointer to it is still valid, queue it now. As
- * with kvm irqfds, we know we won't race against the plat_irqfd
- * going away because we hold the lock to get here.
- */
- if (*(plat_irqfd->pirqfd) == plat_irqfd) {
- *(plat_irqfd->pirqfd) = NULL;
- plat_irqfd_deactivate(plat_irqfd);
- }
-
- spin_unlock_irqrestore(&plat_irqfd_lock, flags);
- }
-
- return 0;
-}
-
-
-static void plat_irqfd_ptable_queue_proc(struct file *file,
- wait_queue_head_t *wqh, poll_table *pt)
-{
- struct plat_irq_forward_irqfd *plat_irqfd =
- container_of(pt, struct plat_irq_forward_irqfd, pt);
- add_wait_queue(wqh, &plat_irqfd->wait);
-}
-
-static void plat_irqfd_shutdown(struct work_struct *work)
-{
- struct plat_irq_forward_irqfd *plat_irqfd = container_of(work,
- struct plat_irq_forward_irqfd, shutdown);
- u64 cnt;
-
- eventfd_ctx_remove_wait_queue(plat_irqfd->eventfd, &plat_irqfd->wait,
- &cnt);
- eventfd_ctx_put(plat_irqfd->eventfd);
-
- kfree(plat_irqfd);
-}
-
-int plat_irq_forward_irqfd_enable(int (*handler)(int, void *), void *data,
- struct plat_irq_forward_irqfd **pirqfd, int fd)
-{
- struct fd irqfd;
- struct eventfd_ctx *ctx;
- struct plat_irq_forward_irqfd *plat_irqfd;
- int ret = 0;
- unsigned int events;
-
- plat_irqfd = kzalloc(sizeof(*plat_irqfd), GFP_KERNEL);
- if (!plat_irqfd)
- return -ENOMEM;
-
- plat_irqfd->pirqfd = pirqfd;
- plat_irqfd->handler = handler;
- plat_irqfd->data = data;
-
- // shutdown causes crash
- INIT_WORK(&plat_irqfd->shutdown, plat_irqfd_shutdown);
-
- irqfd = fdget(fd);
- if (!irqfd.file) {
- ret = -EBADF;
- goto err_fd;
- }
-
- ctx = eventfd_ctx_fileget(irqfd.file);
- if (IS_ERR(ctx)) {
- ret = PTR_ERR(ctx);
- goto err_ctx;
- }
-
- plat_irqfd->eventfd = ctx;
-
- // plat_irqfds can be released by closing the eventfd or directly
- // through ioctl. These are both done through a workqueue, so
- // we update the pointer to the plat_irqfd under lock to avoid
- // pushing multiple jobs to release the same plat_irqfd.
- spin_lock_irq(&plat_irqfd_lock);
-
- if (*pirqfd) {
- pr_emerg("pirqfd should be NULL. BUG!\n");
- spin_unlock_irq(&plat_irqfd_lock);
- ret = -EBUSY;
- goto err_busy;
- }
- *pirqfd = plat_irqfd;
-
- spin_unlock_irq(&plat_irqfd_lock);
-
- // Install our own custom wake-up handling so we are notified via
- // a callback whenever someone signals the underlying eventfd.
- init_waitqueue_func_entry(&plat_irqfd->wait, plat_irqfd_wakeup);
- init_poll_funcptr(&plat_irqfd->pt, plat_irqfd_ptable_queue_proc);
-
- events = irqfd.file->f_op->poll(irqfd.file, &plat_irqfd->pt);
-
- // Check if there was an event already pending on the eventfd
- // before we registered and trigger it as if we didn't miss it.
- if (events & POLLIN) {
- if (!handler || handler(-1, data))
- pr_emerg("handler failed\n");
- }
-
- // Do not drop the file until the irqfd is fully initialized,
- // otherwise we might race against the POLLHUP.
- fdput(irqfd);
-
- return 0;
-err_busy:
- eventfd_ctx_put(ctx);
-err_ctx:
- fdput(irqfd);
-err_fd:
- kfree(plat_irqfd);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(plat_irq_forward_plat_irqfd_enable);
diff --git a/virt/lib/platirqforward.c b/virt/lib/platirqforward.c
deleted file mode 100644
index 3f72a24..0000000
--- a/virt/lib/platirqforward.c
+++ /dev/null
@@ -1,342 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Experimental driver for user space interrupt handler.
- *
- * Copyright 2020 Google LLC
- *
- */
-
-#include <linux/acpi.h>
-#include <linux/cdev.h>
-#include <linux/compat.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/irq.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/vfio.h>
-#include <linux/eventfd.h>
-#include <linux/delay.h>
-#include <uapi/linux/platirqforward.h>
-#include <linux/plat_irqfd.h>
-
-#define VERSION "0.1"
-#define AUTHOR "Micah Morton <mortonm@chromium.org>"
-#define DESC "Platform IRQ Forwarding"
-
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR(AUTHOR);
-MODULE_DESCRIPTION(DESC);
-MODULE_ALIAS("devname:plat-irq-forward");
-
-static LIST_HEAD(level_triggered_irqs);
-static LIST_HEAD(edge_triggered_irqs);
-
-
-static int plat_irq_forward_unmask_handler_level(int irq, void *data)
-{
- unsigned long flags;
- struct plat_irq_forward_level_triggered *l =
- (struct plat_irq_forward_level_triggered *) data;
-
- spin_lock_irqsave(&(l->spinlock), flags);
- if (l->is_masked) {
- enable_irq(l->irq_num);
- l->is_masked = false;
- }
- spin_unlock_irqrestore(&(l->spinlock), flags);
- return 0;
-}
-
-
-static irqreturn_t plat_irq_forward_handler_level(int irq, void *data)
-{
- unsigned long flags;
- int ret = IRQ_NONE;
- struct plat_irq_forward_level_triggered *l =
- (struct plat_irq_forward_level_triggered *) data;
- spin_lock_irqsave(&(l->spinlock), flags);
-
- disable_irq_nosync(irq);
- l->is_masked = true;
- ret = IRQ_HANDLED;
-
- spin_unlock_irqrestore(&(l->spinlock), flags);
-
- if (ret == IRQ_HANDLED)
- eventfd_signal(l->trigger, 1);
-
- return ret;
-}
-
-static irqreturn_t plat_irq_forward_handler_edge(int irq, void *data)
-{
- struct plat_irq_forward_edge_triggered *e =
- (struct plat_irq_forward_edge_triggered *) data;
- eventfd_signal(e->trigger, 1);
-
- return IRQ_HANDLED;
-}
-
-static int plat_irq_forward_set_level_trigger(void *data,
- uint32_t irq_number_host,
- struct plat_irq_forward_level_triggered *level)
-{
- int32_t fd = *(int32_t *)data;
- struct eventfd_ctx *trigger;
- int ret;
-
- if (fd < 0) /* Disable only */
- return 0;
-
- trigger = eventfd_ctx_fdget(fd);
- if (IS_ERR(trigger))
- return PTR_ERR(trigger);
-
- level->trigger = trigger;
- spin_lock_init(&(level->spinlock));
-
- ret = request_irq(irq_number_host, plat_irq_forward_handler_level,
- IRQF_SHARED, "level-triggered-irq", level);
- if (ret == -EINVAL) {
- ret = acpi_register_gsi(NULL, irq_number_host,
- ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
- if (ret < 0) {
- level->trigger = NULL;
- eventfd_ctx_put(trigger);
- return ret;
- }
- ret = request_irq(irq_number_host,
- plat_irq_forward_handler_level,
- IRQF_SHARED, "level-triggered-irq", level);
- }
- if (ret) {
- level->trigger = NULL;
- eventfd_ctx_put(trigger);
- return ret;
- }
-
- return 0;
-}
-
-static int plat_irq_forward_set_level_unmask(void *data,
- struct plat_irq_forward_level_triggered *level)
-{
- int32_t fd = *(int32_t *)data;
-
- if (fd >= 0)
- return plat_irq_forward_irqfd_enable(
- plat_irq_forward_unmask_handler_level,
- level, &(level->unmask), fd);
- return -1;
-}
-
-static int plat_irq_forward_set_edge_trigger(void *data,
- uint32_t irq_number_host,
- struct plat_irq_forward_edge_triggered *edge)
-{
- int32_t fd = *(int32_t *)data;
- struct eventfd_ctx *trigger;
- int ret;
-
- if (fd < 0) /* Disable only */
- return 0;
-
- trigger = eventfd_ctx_fdget(fd);
- if (IS_ERR(trigger))
- return PTR_ERR(trigger);
-
- edge->trigger = trigger;
-
- ret = request_irq(irq_number_host, plat_irq_forward_handler_edge,
- IRQF_SHARED, "edge-triggered-irq", edge);
-
- /* no irq descriptor initialized yet. allocate one owned by
- * irq-forwarder module.
- */
- if (ret == -EINVAL) {
- ret = acpi_register_gsi(NULL, irq_number_host,
- ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW);
- if (ret < 0) {
- edge->trigger = NULL;
- eventfd_ctx_put(trigger);
- return ret;
- }
- ret = request_irq(irq_number_host,
- plat_irq_forward_handler_edge,
- IRQF_SHARED, "edge-triggered-irq", edge);
- }
- if (ret) {
- edge->trigger = NULL;
- eventfd_ctx_put(trigger);
- return ret;
- }
-
- return 0;
-}
-
-
-int platform_set_irqs_ioctl_level_trigger(uint32_t irq_number_host, void *data)
-{
- struct plat_irq_forward_level_triggered *level_irq = kzalloc(
- sizeof(struct plat_irq_forward_level_triggered), GFP_KERNEL);
- if (!level_irq)
- return -ENOMEM;
- level_irq->trigger = NULL;
- level_irq->irq_num = irq_number_host;
- level_irq->unmask = NULL;
- level_irq->is_masked = true;
- list_add(&(level_irq->list), &level_triggered_irqs);
-
- return plat_irq_forward_set_level_trigger(data, irq_number_host,
- level_irq);
-}
-
-int platform_set_irqs_ioctl_level_unmask(uint32_t irq_number_host, void *data)
-{
- struct list_head *position = NULL;
- struct plat_irq_forward_level_triggered *level_irq = NULL;
-
- // We must already have a trigger for the IRQ before we add an unmask
- list_for_each(position, &level_triggered_irqs) {
- level_irq = list_entry(position,
- struct plat_irq_forward_level_triggered,
- list);
- if (level_irq->irq_num == irq_number_host)
- return plat_irq_forward_set_level_unmask(data,
- level_irq);
- }
-
- return -1;
-}
-
-int platform_set_irqs_ioctl_edge_trigger(uint32_t irq_number_host, void *data)
-{
- struct plat_irq_forward_edge_triggered *edge_irq = kzalloc(
- sizeof(struct plat_irq_forward_edge_triggered), GFP_KERNEL);
- if (!edge_irq)
- return -ENOMEM;
- edge_irq->trigger = NULL;
- edge_irq->irq_num = irq_number_host;
- list_add(&(edge_irq->list), &edge_triggered_irqs);
-
- return plat_irq_forward_set_edge_trigger(data, irq_number_host,
- edge_irq);
-}
-
-int plat_irq_forward_ioctl(void *device_data, unsigned long arg)
-{
- u8 *data = NULL;
- unsigned long minsz;
- struct plat_irq_forward_set hdr;
-
- minsz = offsetofend(struct plat_irq_forward_set, count);
-
- if (copy_from_user(&hdr, (void __user *)arg, minsz))
- return -EFAULT;
-
- data = memdup_user((void __user *)(arg + minsz), sizeof(int32_t));
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- switch (hdr.action_flags) {
- case PLAT_IRQ_FORWARD_SET_LEVEL_TRIGGER_EVENTFD:
- return platform_set_irqs_ioctl_level_trigger(
- hdr.irq_number_host, data);
- case PLAT_IRQ_FORWARD_SET_LEVEL_UNMASK_EVENTFD:
- return platform_set_irqs_ioctl_level_unmask(
- hdr.irq_number_host, data);
- case PLAT_IRQ_FORWARD_SET_EDGE_TRIGGER:
- return platform_set_irqs_ioctl_edge_trigger(
- hdr.irq_number_host, data);
- default:
- return -EINVAL;
- }
-
- kfree(data);
- return 0;
-}
-
-/**
- * Platform IRQ Forwarding fd, /dev/plat-irq-forward
- */
-static long plat_irq_forward_fops_unl_ioctl(struct file *filep,
- unsigned int cmd, unsigned long arg)
-{
- long ret = -EINVAL;
-
- switch (cmd) {
- case PLAT_IRQ_FORWARD_SET:
- ret = (long) plat_irq_forward_ioctl(filep, arg);
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static long plat_irq_forward_fops_compat_ioctl(struct file *filep,
- unsigned int cmd, unsigned long arg)
-{
- arg = (unsigned long)compat_ptr(arg);
- return plat_irq_forward_fops_unl_ioctl(filep, cmd, arg);
-}
-#endif /* CONFIG_COMPAT */
-
-static int plat_irq_forward_fops_open(struct inode *inode, struct file *filep)
-{
- return 0;
-}
-
-static int plat_irq_forward_fops_release(struct inode *inode,
- struct file *filep)
-{
- return 0;
-}
-
-static const struct file_operations plat_irq_forward_fops = {
- .owner = THIS_MODULE,
- .open = plat_irq_forward_fops_open,
- .release = plat_irq_forward_fops_release,
- .unlocked_ioctl = plat_irq_forward_fops_unl_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = plat_irq_forward_fops_compat_ioctl,
-#endif
-};
-
-static struct miscdevice plat_irq_forward_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "plat-irq-forward",
- .fops = &plat_irq_forward_fops,
- .nodename = "plat-irq-forward",
- .mode = 0660,
-};
-
-static int __init plat_irq_forward_init(void)
-{
- int ret;
-
- ret = misc_register(&plat_irq_forward_dev);
- if (ret) {
- pr_err("plat-irq-forward: misc device register failed\n");
- return ret;
- }
-
- pr_info(DESC " version: " VERSION "\n");
-
- return 0;
-}
-
-// TODO: cleanup/free/disconnect stuff
-static void __exit plat_irq_forward_cleanup(void)
-{
- misc_deregister(&plat_irq_forward_dev);
-}
-
-module_init(plat_irq_forward_init);
-module_exit(plat_irq_forward_cleanup);