All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philippe  Gerum <rpm@xenomai.org>
To: xenomai@xenomai.org
Subject: [PATCH 1/6] genirq: irq_pipeline: restore oob stall bit on chained IRQs
Date: Thu, 22 Jul 2021 11:48:54 +0200	[thread overview]
Message-ID: <20210722094859.3580166-2-rpm@xenomai.org> (raw)
In-Reply-To: <20210722094859.3580166-1-rpm@xenomai.org>

From: Philippe Gerum <rpm@xenomai.org>

handle_oob_irq() is called recursively when handling chained
interrupts, at which point the oob stage is already stalled:

generic_handle_irq /* oob stage unstalled */
   -> <parent IRQ flow handler>
          -> handle_oob_irq  /* oob stage stalled */
	        -> <parent IRQ demultiplexer>
		       -> generic_handle_irq
			      -> <chained IRQ flow handler>
			             -> handle_oob_irq
				     /* oob stage must stay stalled */
				 ...
		          ...
	           ...

		  /*
		   * oob stage is unstalled upon leaving the outer call
		   * to handle_oob_irq
		   */

Make sure to restore the oob stall bit to its original value on entry
to this routine before leaving it, instead of clearing such bit
unconditionally.

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 kernel/irq/pipeline.c | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/kernel/irq/pipeline.c b/kernel/irq/pipeline.c
index a220d9467a56ce2..090fcc8bbb6a449 100644
--- a/kernel/irq/pipeline.c
+++ b/kernel/irq/pipeline.c
@@ -931,7 +931,7 @@ static inline bool is_active_edge_event(struct irq_desc *desc)
 bool handle_oob_irq(struct irq_desc *desc) /* hardirqs off */
 {
 	struct irq_stage_data *oobd = this_oob_staged();
-	unsigned int irq = irq_desc_get_irq(desc);
+	unsigned int irq = irq_desc_get_irq(desc), s;
 
 	/*
 	 * Flow handlers of chained interrupts have no business
@@ -959,19 +959,8 @@ bool handle_oob_irq(struct irq_desc *desc) /* hardirqs off */
 
 	if (WARN_ON_ONCE(irq_pipeline_debug() && running_inband()))
 		return false;
-	/*
-	 * Running with the oob stage stalled implies hardirqs off, so
-	 * if the oob stage is stalled on pipeline entry, something is
-	 * badly broken in our interrupt state. Pretend the event has
-	 * been handled, which may end up with the device hammering us
-	 * with more interrupts, but there is no safe option at this
-	 * point.
-	 */
-	if (WARN_ON_ONCE(irq_pipeline_debug() &&
-			on_pipeline_entry() && test_oob_stall()))
-		return true;
 
-	stall_oob();
+	s = test_and_stall_oob();
 
 	if (unlikely(desc->istate & IRQS_EDGE)) {
 		do {
@@ -985,7 +974,13 @@ bool handle_oob_irq(struct irq_desc *desc) /* hardirqs off */
 		do_oob_irq(desc);
 	}
 
-	unstall_oob();
+	/*
+	 * Cascaded interrupts enter handle_oob_irq() with the
+	 * out-of-band stage stalled during the parent
+	 * invocation. Make sure to restore accordingly.
+	 */
+	if (likely(!s))
+		unstall_oob();
 
 	/*
 	 * CPU migration and/or stage switching over the handler are
@@ -1060,7 +1055,7 @@ void restore_stage_on_irq(struct irq_stage_data *prevd)
  *	@regs:	Register file coming from the low-level handling code
  *
  *	Inject an IRQ into the pipeline from a CPU interrupt or trap
- *	context.  A flow handler runs for this IRQ.
+ *	context.  A flow handler runs next for this IRQ.
  *
  *      Hard irqs must be off on entry.
  */
@@ -1081,6 +1076,19 @@ int generic_pipeline_irq(unsigned int irq, struct pt_regs *regs)
 			pr_err("IRQ pipeline: interrupts enabled on entry (IRQ%u)\n",
 			       irq);
 		}
+		/*
+		 * Running with the oob stage stalled implies hardirqs
+		 * off.  For this reason, if the oob stage is stalled
+		 * on pipeline entry but we still receive an interrupt
+		 * from the hardware, something is badly broken in our
+		 * interrupt state. Try fixing up, but without great
+		 * hopes.
+		 */
+		if (on_pipeline_entry() && test_oob_stall()) {
+			pr_err("IRQ pipeline: out-of-band stage stalled on IRQ entry\n");
+			unstall_oob();
+		}
+
 		if (unlikely(desc == NULL)) {
 			pr_err("IRQ pipeline: received unhandled IRQ%u\n",
 			       irq);
-- 
2.31.1



  reply	other threads:[~2021-07-22  9:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-22  9:48 Dovetail fixes to v5.3 Philippe Gerum
2021-07-22  9:48 ` Philippe Gerum [this message]
2021-07-22  9:48 ` [PATCH 2/6] gpio: omap: irq_pipeline: enable out-of-band interrupt handling Philippe Gerum
2021-07-22  9:48 ` [PATCH 3/6] drm/msm/mdp5: " Philippe Gerum
2021-07-22  9:48 ` [PATCH 4/6] pinctrl: samsung: " Philippe Gerum
2021-07-22  9:48 ` [PATCH 5/6] genirq: irq_pipeline: export oob status to /proc/interrupts Philippe Gerum
2021-07-22  9:55   ` Jan Kiszka
2021-07-22 10:33     ` Philippe Gerum
2021-07-22  9:48 ` [PATCH 6/6] clocksource/exynos_mct: irq_pipeline: enable out-of-band clock events Philippe Gerum

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=20210722094859.3580166-2-rpm@xenomai.org \
    --to=rpm@xenomai.org \
    --cc=xenomai@xenomai.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.