Commit 6fe5c68e authored by Lorenzo Pieralisi's avatar Lorenzo Pieralisi Committed by Marc Zyngier
Browse files

irqchip/gic-v3: Workaround for GIC-700 erratum 2941627



GIC700 erratum 2941627 may cause GIC-700 missing SPIs wake
requests when SPIs are deactivated while targeting a
sleeping CPU - ie a CPU for which the redistributor:

GICR_WAKER.ProcessorSleep == 1

This runtime situation can happen if an SPI that has been
activated on a core is retargeted to a different core, it
becomes pending and the target core subsequently enters a
power state quiescing the respective redistributor.

When this situation is hit, the de-activation carried out
on the core that activated the SPI (through either ICC_EOIR1_EL1
or ICC_DIR_EL1 register writes) does not trigger a wake
requests for the sleeping GIC redistributor even if the SPI
is pending.

Work around the erratum by de-activating the SPI using the
redistributor GICD_ICACTIVER register if the runtime
conditions require it (ie the IRQ was retargeted between
activation and de-activation).

Signed-off-by: default avatarLorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230704155034.148262-1-lpieralisi@kernel.org
parent 567f67ac
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ stable kernels.
| ARM            | MMU-500         | #841119,826419  | N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | GIC-700         | #2941627        | ARM64_ERRATUM_2941627       |
+----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
+----------------+-----------------+-----------------+-----------------------------+
| Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_843419        |
+61 −1
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ struct gic_chip_data {
static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly;
static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum);

static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum);

static struct gic_chip_data gic_data __read_mostly;
static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);

@@ -592,10 +594,39 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
	gic_irq_set_prio(d, GICD_INT_DEF_PRI);
}

static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
{
	enum gic_intid_range range;

	if (!static_branch_unlikely(&gic_arm64_2941627_erratum))
		return false;

	range = get_intid_range(d);

	/*
	 * The workaround is needed if the IRQ is an SPI and
	 * the target cpu is different from the one we are
	 * executing on.
	 */
	return (range == SPI_RANGE || range == ESPI_RANGE) &&
		!cpumask_test_cpu(raw_smp_processor_id(),
				  irq_data_get_effective_affinity_mask(d));
}

static void gic_eoi_irq(struct irq_data *d)
{
	write_gicreg(gic_irq(d), ICC_EOIR1_EL1);
	isb();

	if (gic_arm64_erratum_2941627_needed(d)) {
		/*
		 * Make sure the GIC stream deactivate packet
		 * issued by ICC_EOIR1_EL1 has completed before
		 * deactivating through GICD_IACTIVER.
		 */
		dsb(sy);
		gic_poke_irq(d, GICD_ICACTIVER);
	}
}

static void gic_eoimode1_eoi_irq(struct irq_data *d)
@@ -606,7 +637,11 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
	 */
	if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d))
		return;

	if (!gic_arm64_erratum_2941627_needed(d))
		gic_write_dir(gic_irq(d));
	else
		gic_poke_irq(d, GICD_ICACTIVER);
}

static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -1816,6 +1851,12 @@ static bool gic_enable_quirk_asr8601(void *data)
	return true;
}

static bool gic_enable_quirk_arm64_2941627(void *data)
{
	static_branch_enable(&gic_arm64_2941627_erratum);
	return true;
}

static const struct gic_quirk gic_quirks[] = {
	{
		.desc	= "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1863,6 +1904,25 @@ static const struct gic_quirk gic_quirks[] = {
		.mask	= 0xffffffff,
		.init	= gic_enable_quirk_nvidia_t241,
	},
	{
		/*
		 * GIC-700: 2941627 workaround - IP variant [0,1]
		 *
		 */
		.desc	= "GICv3: ARM64 erratum 2941627",
		.iidr	= 0x0400043b,
		.mask	= 0xff0e0fff,
		.init	= gic_enable_quirk_arm64_2941627,
	},
	{
		/*
		 * GIC-700: 2941627 workaround - IP variant [2]
		 */
		.desc	= "GICv3: ARM64 erratum 2941627",
		.iidr	= 0x0402043b,
		.mask	= 0xff0f0fff,
		.init	= gic_enable_quirk_arm64_2941627,
	},
	{
	}
};