linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	kernel-team@android.com
Subject: [PATCH 1/2] irqchip/gic: Handle non-standard SGI deactivation on Samsung's Franken-GIC
Date: Tue, 15 Sep 2020 14:39:43 +0100	[thread overview]
Message-ID: <20200915133944.1285456-2-maz@kernel.org> (raw)
In-Reply-To: <20200915133944.1285456-1-maz@kernel.org>

The GIC available on some of Samsung's A9-based platform is
thankfully one of a kind. On top of not presenting a banked
programing model (each CPU has its own base addresses for both
distributor and CPU interface), it also encodes the source CPU
for SGIs in the INTID read from IAR, and requires this exact
value to be written back to EOI.

Without this, interrupts are never deactivated, and the kernel
grinds to a halt.

Work around it by stashing the INTID for in-flight SGIs, and
using that value on EOI. This only works because we don't nest
SGIs.

Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Fixes: ac063232d4b0 ("irqchip/gic: Configure SGIs as standard interrupts")
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic.c | 49 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 4be2b62f816f..84a2d2a1aab7 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -150,10 +150,37 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data,
 {
 	data->get_base = f;
 }
+
+static DEFINE_STATIC_KEY_FALSE(frankengic_key);
+static DEFINE_PER_CPU(u32, sgi_intid);
+
+static void enable_frankengic(void)
+{
+	static_branch_enable(&frankengic_key);
+}
+
+static inline bool is_frankengic(void)
+{
+	return static_branch_unlikely(&frankengic_key);
+}
+
+static inline void set_sgi_intid(u32 intid)
+{
+	this_cpu_write(sgi_intid, intid);
+}
+
+static inline u32 get_sgi_intid(void)
+{
+	return this_cpu_read(sgi_intid);
+}
 #else
 #define gic_data_dist_base(d)	((d)->dist_base.common_base)
 #define gic_data_cpu_base(d)	((d)->cpu_base.common_base)
 #define gic_set_base_accessor(d, f)
+#define enable_frankengic()	do { } while(0)
+#define is_frankengic()		false
+#define set_sgi_intid(i)	do { } while(0)
+#define get_sgi_intid()		0
 #endif
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
@@ -226,7 +253,12 @@ static void gic_unmask_irq(struct irq_data *d)
 
 static void gic_eoi_irq(struct irq_data *d)
 {
-	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+	u32 hwirq = gic_irq(d);
+
+	if (is_frankengic() && hwirq < 16)
+		hwirq = get_sgi_intid();
+
+	writel_relaxed(hwirq, gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
 static void gic_eoimode1_eoi_irq(struct irq_data *d)
@@ -348,8 +380,20 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 		 *
 		 * Pairs with the write barrier in gic_ipi_send_mask
 		 */
-		if (irqnr <= 15)
+		if (irqnr <= 15) {
 			smp_rmb();
+
+			/*
+			 * Samsung's funky GIC encodes the source CPU in
+			 * GICC_IAR, leading to the deactivation to fail if
+			 * not written back as is to GICC_EOI.  Stash the
+			 * INTID away for gic_eoi_irq() to write back.
+			 * This only works because we don't nest SGIs...
+			 */
+			if (is_frankengic())
+				set_sgi_intid(irqstat);
+		}
+
 		handle_domain_irq(gic->domain, irqnr, regs);
 	} while (1);
 }
@@ -1142,6 +1186,7 @@ static int gic_init_bases(struct gic_chip_data *gic,
 				gic->raw_cpu_base + offset;
 		}
 
+		enable_frankengic();
 		gic_set_base_accessor(gic, gic_get_percpu_base);
 	} else {
 		/* Normal, sane GIC... */
-- 
2.28.0


  reply	other threads:[~2020-09-16  0:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-15 13:39 [PATCH 0/2] irqchip/gic: Fix handling of Samsung's non-standard GIC Marc Zyngier
2020-09-15 13:39 ` Marc Zyngier [this message]
2020-09-15 14:06   ` [PATCH 1/2] irqchip/gic: Handle non-standard SGI deactivation on Samsung's Franken-GIC Marek Szyprowski
2020-09-15 14:52     ` Marc Zyngier
2020-09-15 13:39 ` [PATCH 2/2] irqchip/gic: Cleanup Franken-GIC handling Marc Zyngier
2020-09-15 14:06   ` Marek Szyprowski

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=20200915133944.1285456-2-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=jason@lakedaemon.net \
    --cc=kernel-team@android.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=tglx@linutronix.de \
    /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;
as well as URLs for NNTP newsgroup(s).