Re: [PATCH] uio: eliminate extraneous irq thread under CONFIG_PREEMPT_RT

From: Chris Packham

Date: Wed Aug 19 2026 - 16:49:04 EST


Hi Sebastian,

On 20/08/2026 03:06, Sebastian Andrzej Siewior wrote:
> Chris, what was the use case to split this?

I was dealing with having a UIO interrupt for an input on a PCA9539.
There's some more info on the original email thread[1] but basically
because the PCA9539 inputs are nested __setup_irq() enforces that anyone
requesting them does so with a threaded interrupt.

https://lore.kernel.org/all/20240408234050.2056374-3-chris.packham@xxxxxxxxxxxxxxxxxxx/

>
> On 2026-08-19 15:01:00 [+0000], Mike Schanne wrote:
>> Commit f8a27dfa4b82d442af1c0645a5acc70cc97c67f6 ("uio: use threaded
>> interrupts") makes all uio interrupts threaded by default. However
>> under CONFIG_PREEMPT_RT, all interrupts are already threaded. This
>> results in 2 irq threads per uio instance, adding an unnecessary
>> extra context switch per interrupt.
>>
>> Do not request a threaded interrupt for uio under CONFIG_PREEMPT_RT
>>
>> Signed-off-by: Michael Schanne mschanne@xxxxxxx<mailto:mschanne@xxxxxxx>
>> ---
>> drivers/uio/uio.c | 17 +++++++++++++----
>> 1 file changed, 13 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
>> index 004a549c6..4e28777ac 100644
>> --- a/drivers/uio/uio.c
>> +++ b/drivers/uio/uio.c
>> @@ -448,8 +448,12 @@ static irqreturn_t uio_interrupt_handler(int irq, void *dev_id)
>> irqreturn_t ret;
>> ret = idev->info->handler(irq, idev->info);
>> - if (ret == IRQ_HANDLED)
>> - ret = IRQ_WAKE_THREAD;
>> + if (ret == IRQ_HANDLED) {
>> + if (IS_ENABLED(CONFIG_PREEMPT_RT))
>> + uio_event_notify(idev->info);
>> + else
>> + ret = IRQ_WAKE_THREAD;
>> + }
>> return ret;
>> }
>> @@ -1038,8 +1042,13 @@ 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_threaded_irq(info->irq, uio_interrupt_handler, uio_interrupt_thread,
>> - info->irq_flags, info->name, idev);
>> + if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
>> + ret = request_irq(info->irq, uio_interrupt_handler,
>> + info->irq_flags, info->name, idev);
>> + } else {
>> + 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;
> Sebastian