hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/irqchip/irq-gic-v3.c
....@@ -41,6 +41,7 @@
4141
4242 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
4343 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
44
+#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2)
4445
4546 #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
4647
....@@ -49,6 +50,8 @@
4950 phys_addr_t phys_base;
5051 bool single_redist;
5152 };
53
+
54
+static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum);
5255
5356 static struct gic_chip_data gic_data __read_mostly;
5457 static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
....@@ -541,9 +544,39 @@
541544 gic_irq_set_prio(d, GICD_INT_DEF_PRI);
542545 }
543546
547
+static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
548
+{
549
+ enum gic_intid_range range;
550
+
551
+ if (!static_branch_unlikely(&gic_arm64_2941627_erratum))
552
+ return false;
553
+
554
+ range = get_intid_range(d);
555
+
556
+ /*
557
+ * The workaround is needed if the IRQ is an SPI and
558
+ * the target cpu is different from the one we are
559
+ * executing on.
560
+ */
561
+ return (range == SPI_RANGE || range == ESPI_RANGE) &&
562
+ !cpumask_test_cpu(raw_smp_processor_id(),
563
+ irq_data_get_effective_affinity_mask(d));
564
+}
565
+
544566 static void gic_eoi_irq(struct irq_data *d)
545567 {
546
- gic_write_eoir(gic_irq(d));
568
+ write_gicreg(gic_irq(d), ICC_EOIR1_EL1);
569
+ isb();
570
+
571
+ if (gic_arm64_erratum_2941627_needed(d)) {
572
+ /*
573
+ * Make sure the GIC stream deactivate packet
574
+ * issued by ICC_EOIR1_EL1 has completed before
575
+ * deactivating through GICD_IACTIVER.
576
+ */
577
+ dsb(sy);
578
+ gic_poke_irq(d, GICD_ICACTIVER);
579
+ }
547580 }
548581
549582 static void gic_eoimode1_eoi_irq(struct irq_data *d)
....@@ -554,7 +587,11 @@
554587 */
555588 if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d))
556589 return;
557
- gic_write_dir(gic_irq(d));
590
+
591
+ if (!gic_arm64_erratum_2941627_needed(d))
592
+ gic_write_dir(gic_irq(d));
593
+ else
594
+ gic_poke_irq(d, GICD_ICACTIVER);
558595 }
559596
560597 static int gic_set_type(struct irq_data *d, unsigned int type)
....@@ -1472,7 +1509,7 @@
14721509
14731510 /*
14741511 * Make it clear that broken DTs are... broken.
1475
- * Partitionned PPIs are an unfortunate exception.
1512
+ * Partitioned PPIs are an unfortunate exception.
14761513 */
14771514 WARN_ON(*type == IRQ_TYPE_NONE &&
14781515 fwspec->param[0] != GIC_IRQ_TYPE_PARTITION);
....@@ -1603,6 +1640,15 @@
16031640 return true;
16041641 }
16051642
1643
+static bool gic_enable_quirk_mtk_gicr(void *data)
1644
+{
1645
+ struct gic_chip_data *d = data;
1646
+
1647
+ d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
1648
+
1649
+ return true;
1650
+}
1651
+
16061652 static bool gic_enable_quirk_cavium_38539(void *data)
16071653 {
16081654 struct gic_chip_data *d = data;
....@@ -1632,11 +1678,22 @@
16321678 return false;
16331679 }
16341680
1681
+static bool gic_enable_quirk_arm64_2941627(void *data)
1682
+{
1683
+ static_branch_enable(&gic_arm64_2941627_erratum);
1684
+ return true;
1685
+}
1686
+
16351687 static const struct gic_quirk gic_quirks[] = {
16361688 {
16371689 .desc = "GICv3: Qualcomm MSM8996 broken firmware",
16381690 .compatible = "qcom,msm8996-gic-v3",
16391691 .init = gic_enable_quirk_msm8996,
1692
+ },
1693
+ {
1694
+ .desc = "GICv3: Mediatek Chromebook GICR save problem",
1695
+ .property = "mediatek,broken-save-restore-fw",
1696
+ .init = gic_enable_quirk_mtk_gicr,
16401697 },
16411698 {
16421699 .desc = "GICv3: HIP06 erratum 161010803",
....@@ -1664,6 +1721,25 @@
16641721 .init = gic_enable_quirk_cavium_38539,
16651722 },
16661723 {
1724
+ /*
1725
+ * GIC-700: 2941627 workaround - IP variant [0,1]
1726
+ *
1727
+ */
1728
+ .desc = "GICv3: ARM64 erratum 2941627",
1729
+ .iidr = 0x0400043b,
1730
+ .mask = 0xff0e0fff,
1731
+ .init = gic_enable_quirk_arm64_2941627,
1732
+ },
1733
+ {
1734
+ /*
1735
+ * GIC-700: 2941627 workaround - IP variant [2]
1736
+ */
1737
+ .desc = "GICv3: ARM64 erratum 2941627",
1738
+ .iidr = 0x0402043b,
1739
+ .mask = 0xff0f0fff,
1740
+ .init = gic_enable_quirk_arm64_2941627,
1741
+ },
1742
+ {
16671743 }
16681744 };
16691745
....@@ -1674,6 +1750,11 @@
16741750 if (!gic_prio_masking_enabled())
16751751 return;
16761752
1753
+ if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
1754
+ pr_warn("Skipping NMI enable due to firmware issues\n");
1755
+ return;
1756
+ }
1757
+
16771758 ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
16781759 if (!ppi_nmi_refs)
16791760 return;