Skip to content

Commit 74cde1a

Browse files
Xu QiangMarc Zyngier
authored andcommitted
irqchip/gic-v3-its: Unconditionally save/restore the ITS state on suspend
On systems without HW-based collections (i.e. anything except GIC-500), we rely on firmware to perform the ITS save/restore. This doesn't really work, as although FW can properly save everything, it cannot fully restore the state of the command queue (the read-side is reset to the head of the queue). This results in the ITS consuming previously processed commands, potentially corrupting the state. Instead, let's always save the ITS state on suspend, disabling it in the process, and restore the full state on resume. This saves us from broken FW as long as it doesn't enable the ITS by itself (for which we can't do anything). This amounts to simply dropping the ITS_FLAGS_SAVE_SUSPEND_STATE. Signed-off-by: Xu Qiang <[email protected]> [maz: added warning on resume, rewrote commit message] Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d001e41 commit 74cde1a

File tree

1 file changed

+3
-13
lines changed

1 file changed

+3
-13
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)
4343
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
4444
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
45-
#define ITS_FLAGS_SAVE_SUSPEND_STATE (1ULL << 3)
4645

4746
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
4847
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
@@ -4741,9 +4740,6 @@ static int its_save_disable(void)
47414740
list_for_each_entry(its, &its_nodes, entry) {
47424741
void __iomem *base;
47434742

4744-
if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
4745-
continue;
4746-
47474743
base = its->base;
47484744
its->ctlr_save = readl_relaxed(base + GITS_CTLR);
47494745
err = its_force_quiescent(base);
@@ -4762,9 +4758,6 @@ static int its_save_disable(void)
47624758
list_for_each_entry_continue_reverse(its, &its_nodes, entry) {
47634759
void __iomem *base;
47644760

4765-
if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
4766-
continue;
4767-
47684761
base = its->base;
47694762
writel_relaxed(its->ctlr_save, base + GITS_CTLR);
47704763
}
@@ -4784,17 +4777,17 @@ static void its_restore_enable(void)
47844777
void __iomem *base;
47854778
int i;
47864779

4787-
if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
4788-
continue;
4789-
47904780
base = its->base;
47914781

47924782
/*
47934783
* Make sure that the ITS is disabled. If it fails to quiesce,
47944784
* don't restore it since writing to CBASER or BASER<n>
47954785
* registers is undefined according to the GIC v3 ITS
47964786
* Specification.
4787+
*
4788+
* Firmware resuming with the ITS enabled is terminally broken.
47974789
*/
4790+
WARN_ON(readl_relaxed(base + GITS_CTLR) & GITS_CTLR_ENABLE);
47984791
ret = its_force_quiescent(base);
47994792
if (ret) {
48004793
pr_err("ITS@%pa: failed to quiesce on resume: %d\n",
@@ -5074,9 +5067,6 @@ static int __init its_probe_one(struct resource *res,
50745067
ctlr |= GITS_CTLR_ImDe;
50755068
writel_relaxed(ctlr, its->base + GITS_CTLR);
50765069

5077-
if (GITS_TYPER_HCC(typer))
5078-
its->flags |= ITS_FLAGS_SAVE_SUSPEND_STATE;
5079-
50805070
err = its_init_domain(handle, its);
50815071
if (err)
50825072
goto out_free_tables;

0 commit comments

Comments
 (0)