|
@@ -1879,16 +1879,6 @@ static void its_cpu_init_lpis(void)
|
|
|
gic_data_rdist()->pend_page = pend_page;
|
|
|
}
|
|
|
|
|
|
- /* Disable LPIs */
|
|
|
- val = readl_relaxed(rbase + GICR_CTLR);
|
|
|
- val &= ~GICR_CTLR_ENABLE_LPIS;
|
|
|
- writel_relaxed(val, rbase + GICR_CTLR);
|
|
|
-
|
|
|
- /*
|
|
|
- * Make sure any change to the table is observable by the GIC.
|
|
|
- */
|
|
|
- dsb(sy);
|
|
|
-
|
|
|
/* set PROPBASE */
|
|
|
val = (page_to_phys(gic_rdists->prop_page) |
|
|
|
GICR_PROPBASER_InnerShareable |
|
|
@@ -3403,13 +3393,69 @@ static bool gic_rdists_supports_plpis(void)
|
|
|
return !!(gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER) & GICR_TYPER_PLPIS);
|
|
|
}
|
|
|
|
|
|
+static int redist_disable_lpis(void)
|
|
|
+{
|
|
|
+ void __iomem *rbase = gic_data_rdist_rd_base();
|
|
|
+ u64 timeout = USEC_PER_SEC;
|
|
|
+ u64 val;
|
|
|
+
|
|
|
+ if (!gic_rdists_supports_plpis()) {
|
|
|
+ pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ val = readl_relaxed(rbase + GICR_CTLR);
|
|
|
+ if (!(val & GICR_CTLR_ENABLE_LPIS))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ pr_warn("CPU%d: Booted with LPIs enabled, memory probably corrupted\n",
|
|
|
+ smp_processor_id());
|
|
|
+ add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
|
|
|
+
|
|
|
+ /* Disable LPIs */
|
|
|
+ val &= ~GICR_CTLR_ENABLE_LPIS;
|
|
|
+ writel_relaxed(val, rbase + GICR_CTLR);
|
|
|
+
|
|
|
+ /* Make sure any change to GICR_CTLR is observable by the GIC */
|
|
|
+ dsb(sy);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Software must observe RWP==0 after clearing GICR_CTLR.EnableLPIs
|
|
|
+ * from 1 to 0 before programming GICR_PEND{PROP}BASER registers.
|
|
|
+ * Error out if we time out waiting for RWP to clear.
|
|
|
+ */
|
|
|
+ while (readl_relaxed(rbase + GICR_CTLR) & GICR_CTLR_RWP) {
|
|
|
+ if (!timeout) {
|
|
|
+ pr_err("CPU%d: Timeout while disabling LPIs\n",
|
|
|
+ smp_processor_id());
|
|
|
+ return -ETIMEDOUT;
|
|
|
+ }
|
|
|
+ udelay(1);
|
|
|
+ timeout--;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * After it has been written to 1, it is IMPLEMENTATION
|
|
|
+ * DEFINED whether GICR_CTLR.EnableLPI becomes RES1 or can be
|
|
|
+ * cleared to 0. Error out if clearing the bit failed.
|
|
|
+ */
|
|
|
+ if (readl_relaxed(rbase + GICR_CTLR) & GICR_CTLR_ENABLE_LPIS) {
|
|
|
+ pr_err("CPU%d: Failed to disable LPIs\n", smp_processor_id());
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int its_cpu_init(void)
|
|
|
{
|
|
|
if (!list_empty(&its_nodes)) {
|
|
|
- if (!gic_rdists_supports_plpis()) {
|
|
|
- pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
|
|
|
- return -ENXIO;
|
|
|
- }
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = redist_disable_lpis();
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
its_cpu_init_lpis();
|
|
|
its_cpu_init_collections();
|
|
|
}
|