diff options
author | Chris Packham <chris.packham@alliedtelesis.co.nz> | 2024-04-09 02:40:49 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-04-11 15:40:29 +0300 |
commit | f8a27dfa4b82d442af1c0645a5acc70cc97c67f6 (patch) | |
tree | f649171f145c5bfeefcf5e96138bd8dc0ba8b206 | |
parent | 90fa0280553a87d0db51dd04f1aea1c2dde53c74 (diff) | |
download | linux-f8a27dfa4b82d442af1c0645a5acc70cc97c67f6.tar.xz |
uio: use threaded interrupts
Split the existing uio_interrupt into a hardirq handler and a thread
function. The hardirq handler deals with the interrupt source in
hardware, the thread function notifies userspace that there is an event
to be handled.
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Link: https://lore.kernel.org/r/20240408234050.2056374-3-chris.packham@alliedtelesis.co.nz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/uio/uio.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 009158fef2a8..e815856eb46c 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -442,18 +442,27 @@ EXPORT_SYMBOL_GPL(uio_event_notify); * @irq: IRQ number, can be UIO_IRQ_CYCLIC for cyclic timer * @dev_id: Pointer to the devices uio_device structure */ -static irqreturn_t uio_interrupt(int irq, void *dev_id) +static irqreturn_t uio_interrupt_handler(int irq, void *dev_id) { struct uio_device *idev = (struct uio_device *)dev_id; irqreturn_t ret; ret = idev->info->handler(irq, idev->info); if (ret == IRQ_HANDLED) - uio_event_notify(idev->info); + ret = IRQ_WAKE_THREAD; return ret; } +static irqreturn_t uio_interrupt_thread(int irq, void *dev_id) +{ + struct uio_device *idev = (struct uio_device *)dev_id; + + uio_event_notify(idev->info); + + return IRQ_HANDLED; +} + struct uio_listener { struct uio_device *dev; s32 event_count; @@ -1024,8 +1033,8 @@ int __uio_register_device(struct module *owner, * FDs at the time of unregister and therefore may not be * freed until they are released. */ - ret = request_irq(info->irq, uio_interrupt, - info->irq_flags, info->name, idev); + ret = request_threaded_irq(info->irq, uio_interrupt_handler, uio_interrupt_thread, + info->irq_flags, info->name, idev); if (ret) { info->uio_dev = NULL; goto err_request_irq; |