diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 3c755d5dad6e..53cf50dd8e13 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -29,6 +29,7 @@
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <linux/syscore_ops.h>
+#include <linux/workqueue.h>
 
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic-v3.h>
@@ -49,6 +50,7 @@
 #define RD_LOCAL_MEMRESERVE_DONE                BIT(2)
 
 static u32 lpi_id_bits;
+static u32 lpi_id_base __initdata = 8192;
 
 /*
  * We allocate memory for PROPBASE to cover 2 ^ lpi_id_bits LPIs to
@@ -2136,7 +2138,7 @@ static int __init its_lpi_init(u32 id_bits)
 	 * Initializing the allocator is just the same as freeing the
 	 * full range of LPIs.
 	 */
-	err = free_lpi_range(8192, lpis);
+	err = free_lpi_range(lpi_id_base, lpis - lpi_id_base + 8192);
 	pr_debug("ITS: Allocator initialized for %u LPIs\n", lpis);
 	return err;
 }
@@ -4763,6 +4765,61 @@ static bool its_set_non_coherent(void *data)
 	return true;
 }
 
+#define ITS_QUIRK_GIC700_2195890_PERIOD_MSEC 1000
+static struct {
+	u32 lpi;
+	struct delayed_work work;
+} its_quirk_gic700_2195890_data __maybe_unused;
+
+static void __maybe_unused its_quirk_gic700_2195890_work_handler(struct work_struct *work)
+{
+	int cpu;
+	void __iomem *rdbase;
+	u64 gicr_invlpir_val;
+
+	for_each_online_cpu(cpu) {
+		rdbase = gic_data_rdist_cpu(cpu)->rd_base;
+		if (!rdbase) {
+			continue;
+		}
+
+		/*
+		 * Prod the respective GIC with an INV for an otherwise unused
+		 * LPI.  This is only to resume the stalled processing, so
+		 * there's no need to wait for invalidation to complete.
+		 */
+		gicr_invlpir_val =
+			FIELD_PREP(GICR_INVLPIR_INTID,
+				   its_quirk_gic700_2195890_data.lpi);
+		raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
+		gic_write_lpir(gicr_invlpir_val, rdbase + GICR_INVLPIR);
+		raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+	}
+
+	schedule_delayed_work(&its_quirk_gic700_2195890_data.work,
+		msecs_to_jiffies(ITS_QUIRK_GIC700_2195890_PERIOD_MSEC));
+}
+
+static bool __maybe_unused its_enable_quirk_gic700_2195890(void *data)
+{
+	struct its_node *its = data;
+
+	if (its_quirk_gic700_2195890_data.lpi)
+		return true;
+
+	/*
+	 * Use one LPI INTID from the start of the LPI range for GIC prodding,
+	 * and make it unavailable for regular LPI use later.
+	 */
+	its_quirk_gic700_2195890_data.lpi = lpi_id_base++;
+
+	INIT_DELAYED_WORK(&its_quirk_gic700_2195890_data.work,
+			  its_quirk_gic700_2195890_work_handler);
+	schedule_delayed_work(&its_quirk_gic700_2195890_data.work, 0);
+
+	return true;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
 	{
@@ -4822,6 +4879,17 @@ static const struct gic_quirk its_quirks[] = {
 		.property = "dma-noncoherent",
 		.init   = its_set_non_coherent,
 	},
+#ifdef CONFIG_ARM64_ERRATUM_2195890
+	{
+		.desc	= "ITS: GIC-700 erratum 2195890",
+		/*
+		 * Applies to r0p0, r0p1, r1p0: iidr_var(bits 16..19) == 0 or 1
+		 */
+		.iidr	= 0x0400043b,
+		.mask	= 0xfffeffff,
+		.init	= its_enable_quirk_gic700_2195890,
+	},
+#endif
 	{
 	}
 };
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index eb8af8032c31..67445075ae88 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -169,6 +169,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | GIC-700         | #2941627        | ARM64_ERRATUM_2941627       |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | GIC-700         | #2195890        | ARM64_ERRATUM_2195890       |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
 +----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d91259ee7b5..9c330029131c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1279,6 +1279,24 @@ config ROCKCHIP_ERRATUM_3588001
 
 	  If unsure, say Y.
 
+config ARM64_ERRATUM_2195890
+	bool "GIC-700: 2195890: LPIs may be held in Pending Table until specific external events happen"
+	default y
+	help
+	  This option adds a workaround for Arm GIC-700 erratum 2195890.
+
+	  In affected GIC-700 versions (r0p0, r0p1, r1p0) under certain
+	  conditions LPIs may remain in the Pending Table until one of a number
+	  of external events occurs.
+
+	  No LPIs are lost and this can happen on physical or virtual PEs but
+	  this erratum means they may not be delivered in a finite time.
+
+	  Work around the issue by inserting an INV command for an unused but
+	  valid LPI INTID every so often to retrigger the search.
+
+	  If unsure, say Y.
+
 config SOCIONEXT_SYNQUACER_PREITS
 	bool "Socionext Synquacer: Workaround for GICv3 pre-ITS"
 	default y
