public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Wei Gong <gongwei833x@gmail.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3] genirq: avoid long loops in handle_edge_irq
Date: Thu, 19 Oct 2023 10:28:58 +0200	[thread overview]
Message-ID: <87zg0f2eyd.ffs@tglx> (raw)
In-Reply-To: <ZTDUiXnb_Sn-5bT2@MacBook-Pro-3.local>

On Thu, Oct 19 2023 at 15:02, Wei Gong wrote:
> O Fri, Oct 13, 2023 at 10:44:36AM +0200, Thomas Gleixner wrote:
>> > By maintaining the original loop exit condition, if a mask mismatch is 
>> > detected within the loop, we will not perform the unmask_irq operation. 
>> > Instead, we will wait until the loop exits before executing unmask_irq.
>> > Could this approach potentially solve the issue of lost interrupts?
>> 
>> How so exactly?
>> 
> diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
> index 8f8f1d62f..b846659ce 100644
> --- a/kernel/irq/chip.c
> +++ b/kernel/irq/chip.c
> @@ -823,7 +823,9 @@ void handle_edge_irq(struct irq_desc *desc)
>  		 */
>  		if (unlikely(desc->istate & IRQS_PENDING)) {
>  			if (!irqd_irq_disabled(&desc->irq_data) &&
> -			    irqd_irq_masked(&desc->irq_data))
> +			    irqd_irq_masked(&desc->irq_data) &&
> +			    cpumask_test_cpu(smp_processor_id(),
> +				    irq_data_get_effective_affinity_mask(&desc->irq_data)))
>  				unmask_irq(desc);
>  		}
>  
> @@ -832,6 +834,10 @@ void handle_edge_irq(struct irq_desc *desc)
>  	} while ((desc->istate & IRQS_PENDING) &&
>  		 !irqd_irq_disabled(&desc->irq_data));
>  
> +if (!irqd_irq_disabled(&desc->irq_data) &&
> +    irqd_irq_masked(&desc->irq_data))
> +	unmask_irq(desc);

What is this supposed to solve? The last interrupt has been delivered
already. It's the one which sets the PENDING bit.

Again:

    CPU 0                                CPU 1

    interrupt #1
	 set IN_PROGRESS
	 do {
					 change_affinity_to(CPU1);
	    handle_irq_event()
		 ack_in_device(interrupt #1)

					 interrupt #2
					    set PENDING
                                            mask();
	 } while (COND)

         unmask();

The unmask does not make the interrupt #2 magically reappear. This is
edge, which is a fire and forget mechanism. That's why we have the
PENDING bit logic for edge to ensure that no interrupt is lost.

With your change interrupt #2 is lost forever.

So if the device depends on ack_in_device() for being able to send the
next interrupt, then the lack of ack_in_device() for interrupt #2 makes
it stale.

It may well be that your particular device does not need the
ack_in_device() sequence, but this is generic core code which has to
work for everything.

I'm still having a hard time to understand why this is such a big
issue at all. What's the practical impact of processing a bunch of
interrupts on CPU0 after changing the affinity to CPU1?

  It's obviously suboptimal in terms of locality, but that's a temporary
  problem which resolves itself. It's suboptimal, but correct behaviour.

Your attempts of "fixing" it at the core edge handler level result in a
fundamental correctness problem.

There are certainly ways to solve it at that level, but for that you
have to fully understand and accept the fundamental properties and
intricacies of edge triggered interrupts in the first place.

Whether the resulting complexity is worth it, is a different
question. As long as there is not a compelling reason to do so, the
answer is simply no.

Thanks,

        tglx

  reply	other threads:[~2023-10-19  8:29 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-28 10:06 [PATCH v3] genirq: avoid long loops in handle_edge_irq Wei Gong
2023-10-09 14:32 ` Thomas Gleixner
2023-10-12 13:39   ` Wei Gong
2023-10-13  8:44     ` Thomas Gleixner
2023-10-19  7:02       ` Wei Gong
2023-10-19  8:28         ` Thomas Gleixner [this message]
2023-10-19  9:37           ` Wei Gong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zg0f2eyd.ffs@tglx \
    --to=tglx@linutronix.de \
    --cc=gongwei833x@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox