All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: zhengyan <zhengyan@asrmicro.com>
Cc: linux-kernel@vger.kernel.org, meitaogao@asrmicro.com,
	qiaozhou@asrmicro.com, tglx@linutronix.de,
	zhizhouzhang@asrmicro.com
Subject: Re: [PATCH v2] irqchip/gic-v3: workaround for ASR8601 when reading mpidr
Date: Mon, 29 May 2023 16:02:13 +0100	[thread overview]
Message-ID: <87sfbfji4q.wl-maz@kernel.org> (raw)
In-Reply-To: <20230522110643.3063073-1-zhengyan@asrmicro.com>

On Mon, 22 May 2023 12:06:43 +0100,
zhengyan <zhengyan@asrmicro.com> wrote:
> 
> This patch add workaround for ASR8601, which uses an armv8.2
> processor with a gic-500. But gic-500 is incompatible with
> ARMv8.2 implementations from ARM.
> 
> ARMv8.2 from ARM implementation uses Multiprocessor Affinity
> Register to identify the logical address of the core by
> | cluster | core | thread |.
> However, gic-500 only supports topologies with
> affinity levels less than 2 as
> | cluster | core|.
> 
> So we need this patch as workaround to shift the MPIDR values
> to ensure proper functionality
> 
> Signed-off-by: zhengyan <zhengyan@asrmicro.com>
> ---
>  Documentation/arm64/silicon-errata.rst |  4 ++++
>  drivers/irqchip/irq-gic-v3.c           | 30 ++++++++++++++++++++++++++
>  2 files changed, 34 insertions(+)
> 
> diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
> index 9e311bc43e05..d6430ade349d 100644
> --- a/Documentation/arm64/silicon-errata.rst
> +++ b/Documentation/arm64/silicon-errata.rst
> @@ -214,3 +214,7 @@ stable kernels.
>  +----------------+-----------------+-----------------+-----------------------------+
>  | Fujitsu        | A64FX           | E#010001        | FUJITSU_ERRATUM_010001      |
>  +----------------+-----------------+-----------------+-----------------------------+
> +
> ++----------------+-----------------+-----------------+-----------------------------+
> +| ASR            | ASR8601         | #8601001        | N/A                         |
> ++----------------+-----------------+-----------------+-----------------------------+
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 6fcee221f201..cf64783dfe70 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -39,6 +39,9 @@
>  
>  #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996	(1ULL << 0)
>  #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539	(1ULL << 1)
> +#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001	(1ULL << 2)
> +
> +#define ASR8601_AFF_QUIRK(aff)			(aff >> 8)

This is wrong. There are more than just affinity bits in MPIDR, and
you're making a mess of the result.

>  
>  #define GIC_IRQ_TYPE_PARTITION	(GIC_IRQ_TYPE_LPI + 1)
>  
> @@ -659,6 +662,9 @@ static u64 gic_mpidr_to_affinity(unsigned long mpidr)
>  {
>  	u64 aff;
>  
> +	if (gic_data.flags & FLAGS_WORKAROUND_ASR_ERRATUM_8601001)
> +		mpidr = ASR8601_AFF_QUIRK(mpidr);
> +
>  	aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
>  	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
>  	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |
> @@ -970,6 +976,9 @@ static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
>  	 * Convert affinity to a 32bit value that can be matched to
>  	 * GICR_TYPER bits [63:32].
>  	 */
> +	if (gic_data.flags & FLAGS_WORKAROUND_ASR_ERRATUM_8601001)
> +		mpidr = ASR8601_AFF_QUIRK(mpidr);

It really wasn't what I had in mind when I asked you to place this
inside a helper. The whole thing looks horrible, and I really don't
want to have to maintain anything like it.

I came up with the following patch, which keeps the workaround *in a
single spot*.

Let me know if that works for you.

	M.

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6fcee221f201..b7d69ef4da9f 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -39,6 +39,7 @@
 
 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996	(1ULL << 0)
 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539	(1ULL << 1)
+#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001	(1ULL << 2)
 
 #define GIC_IRQ_TYPE_PARTITION	(GIC_IRQ_TYPE_LPI + 1)
 
@@ -655,10 +656,16 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 	return 0;
 }
 
-static u64 gic_mpidr_to_affinity(unsigned long mpidr)
+static u64 gic_cpu_to_affinity(int cpu)
 {
+	u64 mpidr = cpu_logical_map(cpu);
 	u64 aff;
 
+	/* ASR8601 needs to have its affinities shifted down... */
+	if (unlikely(gic_data.flags & FLAGS_WORKAROUND_ASR_ERRATUM_8601001))
+		mpidr = (MPIDR_AFFINITY_LEVEL(mpidr, 1)	|
+			 (MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8));
+
 	aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
 	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
 	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |
@@ -913,7 +920,7 @@ static void __init gic_dist_init(void)
 	 * Set all global interrupts to the boot CPU only. ARE must be
 	 * enabled.
 	 */
-	affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
+	affinity = gic_cpu_to_affinity(smp_processor_id());
 	for (i = 32; i < GIC_LINE_NR; i++)
 		gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
 
@@ -962,7 +969,7 @@ static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
 
 static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
 {
-	unsigned long mpidr = cpu_logical_map(smp_processor_id());
+	unsigned long mpidr;
 	u64 typer;
 	u32 aff;
 
@@ -970,6 +977,8 @@ static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
 	 * Convert affinity to a 32bit value that can be matched to
 	 * GICR_TYPER bits [63:32].
 	 */
+	mpidr = gic_cpu_to_affinity(smp_processor_id());
+
 	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
 	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
 	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
@@ -1262,9 +1271,11 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
 				   unsigned long cluster_id)
 {
 	int next_cpu, cpu = *base_cpu;
-	unsigned long mpidr = cpu_logical_map(cpu);
+	unsigned long mpidr;
 	u16 tlist = 0;
 
+	mpidr = gic_cpu_to_affinity(cpu);
+
 	while (cpu < nr_cpu_ids) {
 		tlist |= 1 << (mpidr & 0xf);
 
@@ -1273,8 +1284,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
 			goto out;
 		cpu = next_cpu;
 
-		mpidr = cpu_logical_map(cpu);
-
+		mpidr = gic_cpu_to_affinity(cpu);
 		if (cluster_id != MPIDR_TO_SGI_CLUSTER_ID(mpidr)) {
 			cpu--;
 			goto out;
@@ -1318,7 +1328,7 @@ static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
 	dsb(ishst);
 
 	for_each_cpu(cpu, mask) {
-		u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(cpu_logical_map(cpu));
+		u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(gic_cpu_to_affinity(cpu));
 		u16 tlist;
 
 		tlist = gic_compute_target_list(&cpu, mask, cluster_id);
@@ -1376,7 +1386,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 
 	offset = convert_offset_index(d, GICD_IROUTER, &index);
 	reg = gic_dist_base(d) + offset + (index * 8);
-	val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
+	val = gic_cpu_to_affinity(cpu);
 
 	gic_write_irouter(val, reg);
 
@@ -1786,6 +1796,15 @@ static bool gic_enable_quirk_nvidia_t241(void *data)
 	return true;
 }
 
+static bool gic_enable_quirk_asr8601(void *data)
+{
+	struct gic_chip_data *d = data;
+
+	d->flags |= FLAGS_WORKAROUND_ASR_ERRATUM_8601001;
+
+	return true;
+}
+
 static const struct gic_quirk gic_quirks[] = {
 	{
 		.desc	= "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1823,6 +1842,11 @@ static const struct gic_quirk gic_quirks[] = {
 		.mask	= 0xffffffff,
 		.init	= gic_enable_quirk_nvidia_t241,
 	},
+	{
+		.desc	= "GICv3: ASR erratum 8601001",
+		.compatible = "asr,asr8601-gic-v3",
+		.init	= gic_enable_quirk_asr8601,
+	},
 	{
 	}
 };


-- 
Without deviation from the norm, progress is not possible.

  reply	other threads:[~2023-05-29 15:02 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-17  7:55 [PATCH] irqchip/gic-v3: workaround for ASR8601 when reading mpidr zhengyan
2023-05-17  8:32 ` Marc Zyngier
2023-05-17 10:45   ` Yan Zheng(严政)
2023-05-17 12:59     ` Marc Zyngier
2023-05-18  3:15       ` Yan Zheng(严政)
2023-05-18  7:23         ` Marc Zyngier
2023-05-22 11:06 ` [PATCH v2] " zhengyan
2023-05-29 15:02   ` Marc Zyngier [this message]
2023-05-30  6:07     ` Yan Zheng(严政)
2023-05-30  7:15       ` Marc Zyngier

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=87sfbfji4q.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=meitaogao@asrmicro.com \
    --cc=qiaozhou@asrmicro.com \
    --cc=tglx@linutronix.de \
    --cc=zhengyan@asrmicro.com \
    --cc=zhizhouzhang@asrmicro.com \
    /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.