Skip to content

Commit 1d816ba

Browse files
diandersctmarinas
authored andcommitted
arm64: Move MediaTek GIC quirk handling from irqchip to core
In commit 44bd78d ("irqchip/gic-v3: Disable pseudo NMIs on MediaTek devices w/ firmware issues") we added a method for detecting MediaTek devices with broken firmware and disabled pseudo-NMI. While that worked, it didn't address the problem at a deep enough level. The fundamental issue with this broken firmware is that it's not saving and restoring several important GICR registers. The current list is believed to be: * GICR_NUM_IPRIORITYR * GICR_CTLR * GICR_ISPENDR0 * GICR_ISACTIVER0 * GICR_NSACR Pseudo-NMI didn't work because it was the only thing (currently) in the kernel that relied on the broken registers, so forcing pseudo-NMI off was an effective fix. However, it could be observed that calling system_uses_irq_prio_masking() on these systems still returned "true". That caused confusion and led to the need for commit a07a594 ("arm64: smp: avoid NMI IPIs with broken MediaTek FW"). It's worried that the incorrect value returned by system_uses_irq_prio_masking() on these systems will continue to confuse future developers. Let's fix the issue a little more completely by disabling IRQ priorities at a deeper level in the kernel. Once we do this we can revert some of the other bits of code dealing with this quirk. This includes a partial revert of commit 44bd78d ("irqchip/gic-v3: Disable pseudo NMIs on MediaTek devices w/ firmware issues"). This isn't a full revert because it leaves some of the changes to the "quirks" structure around in case future code needs it. Suggested-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Acked-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20231107072651.v2.1.Ide945748593cffd8ff0feb9ae22b795935b944d6@changeid Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 403edfa commit 1d816ba

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

arch/arm64/kernel/cpufeature.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,37 @@ static void init_32bit_cpu_features(struct cpuinfo_32bit *info)
999999
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
10001000
}
10011001

1002+
#ifdef CONFIG_ARM64_PSEUDO_NMI
1003+
static bool enable_pseudo_nmi;
1004+
1005+
static int __init early_enable_pseudo_nmi(char *p)
1006+
{
1007+
return kstrtobool(p, &enable_pseudo_nmi);
1008+
}
1009+
early_param("irqchip.gicv3_pseudo_nmi", early_enable_pseudo_nmi);
1010+
1011+
static __init void detect_system_supports_pseudo_nmi(void)
1012+
{
1013+
struct device_node *np;
1014+
1015+
if (!enable_pseudo_nmi)
1016+
return;
1017+
1018+
/*
1019+
* Detect broken MediaTek firmware that doesn't properly save and
1020+
* restore GIC priorities.
1021+
*/
1022+
np = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
1023+
if (np && of_property_read_bool(np, "mediatek,broken-save-restore-fw")) {
1024+
pr_info("Pseudo-NMI disabled due to MediaTek Chromebook GICR save problem\n");
1025+
enable_pseudo_nmi = false;
1026+
}
1027+
of_node_put(np);
1028+
}
1029+
#else /* CONFIG_ARM64_PSEUDO_NMI */
1030+
static inline void detect_system_supports_pseudo_nmi(void) { }
1031+
#endif
1032+
10021033
void __init init_cpu_features(struct cpuinfo_arm64 *info)
10031034
{
10041035
/* Before we start using the tables, make sure it is sorted */
@@ -1057,6 +1088,13 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
10571088
*/
10581089
init_cpucap_indirect_list();
10591090

1091+
/*
1092+
* Detect broken pseudo-NMI. Must be called _before_ the call to
1093+
* setup_boot_cpu_capabilities() since it interacts with
1094+
* can_use_gic_priorities().
1095+
*/
1096+
detect_system_supports_pseudo_nmi();
1097+
10601098
/*
10611099
* Detect and enable early CPU capabilities based on the boot CPU,
10621100
* after we have initialised the CPU feature infrastructure.
@@ -2085,14 +2123,6 @@ static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap)
20852123
#endif /* CONFIG_ARM64_E0PD */
20862124

20872125
#ifdef CONFIG_ARM64_PSEUDO_NMI
2088-
static bool enable_pseudo_nmi;
2089-
2090-
static int __init early_enable_pseudo_nmi(char *p)
2091-
{
2092-
return kstrtobool(p, &enable_pseudo_nmi);
2093-
}
2094-
early_param("irqchip.gicv3_pseudo_nmi", early_enable_pseudo_nmi);
2095-
20962126
static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
20972127
int scope)
20982128
{

drivers/irqchip/irq-gic-v3.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939

4040
#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
4141
#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
42-
#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2)
43-
#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 3)
42+
#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 2)
4443

4544
#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
4645

@@ -1779,15 +1778,6 @@ static bool gic_enable_quirk_msm8996(void *data)
17791778
return true;
17801779
}
17811780

1782-
static bool gic_enable_quirk_mtk_gicr(void *data)
1783-
{
1784-
struct gic_chip_data *d = data;
1785-
1786-
d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
1787-
1788-
return true;
1789-
}
1790-
17911781
static bool gic_enable_quirk_cavium_38539(void *data)
17921782
{
17931783
struct gic_chip_data *d = data;
@@ -1880,11 +1870,6 @@ static const struct gic_quirk gic_quirks[] = {
18801870
.compatible = "asr,asr8601-gic-v3",
18811871
.init = gic_enable_quirk_asr8601,
18821872
},
1883-
{
1884-
.desc = "GICv3: Mediatek Chromebook GICR save problem",
1885-
.property = "mediatek,broken-save-restore-fw",
1886-
.init = gic_enable_quirk_mtk_gicr,
1887-
},
18881873
{
18891874
.desc = "GICv3: HIP06 erratum 161010803",
18901875
.iidr = 0x0204043b,
@@ -1946,11 +1931,6 @@ static void gic_enable_nmi_support(void)
19461931
if (!gic_prio_masking_enabled())
19471932
return;
19481933

1949-
if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
1950-
pr_warn("Skipping NMI enable due to firmware issues\n");
1951-
return;
1952-
}
1953-
19541934
rdist_nmi_refs = kcalloc(gic_data.ppi_nr + SGI_NR,
19551935
sizeof(*rdist_nmi_refs), GFP_KERNEL);
19561936
if (!rdist_nmi_refs)

0 commit comments

Comments
 (0)