drivers/irqchip/irq-gic-v3-its.c | 4 ++++ include/linux/irqchip/arm-gic-v3.h | 1 + 2 files changed, 5 insertions(+)
The ITS driver blindly assumes that EventIDs are in abundant supply,
to the point where it never checks how many the HW actually supports.
It turns out that some pretty esoteric integrations make it so that
only a few bits are available, all the way down to a. single. bit.
Enforce the advertised limitation at the point of allocating the
device structure, and hope that the endpoint driver can deal with
such limitation.
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
---
drivers/irqchip/irq-gic-v3-its.c | 4 ++++
include/linux/irqchip/arm-gic-v3.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2988def30972b..a51e8e6a81819 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
int lpi_base;
int nr_lpis;
int nr_ites;
+ int id_bits;
int sz;
if (!its_alloc_device_table(its, dev_id))
@@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
/*
* Even if the device wants a single LPI, the ITT must be
* sized as a power of two (and you need at least one bit...).
+ * Also honor the ITS's own EID limit.
*/
+ id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+ nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
sz = max(sz, ITS_ITT_ALIGN);
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 70c0948f978eb..0225121f30138 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -394,6 +394,7 @@
#define GITS_TYPER_VLPIS (1UL << 1)
#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4
#define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS GENMASK_ULL(12, 8)
#define GITS_TYPER_IDBITS_SHIFT 8
#define GITS_TYPER_DEVBITS_SHIFT 13
#define GITS_TYPER_DEVBITS GENMASK_ULL(17, 13)
--
2.47.3
On 2026-02-06 3:48 pm, Marc Zyngier wrote: > The ITS driver blindly assumes that EventIDs are in abundant supply, > to the point where it never checks how many the HW actually supports. > > It turns out that some pretty esoteric integrations make it so that > only a few bits are available, all the way down to a. single. bit. > > Enforce the advertised limitation at the point of allocating the > device structure, and hope that the endpoint driver can deal with > such limitation. Reviewed-by: Robin Murphy <robin.murphy@arm.com> > Signed-off-by: Marc Zyngier <maz@kernel.org> > Cc: stable@vger.kernel.org > --- > drivers/irqchip/irq-gic-v3-its.c | 4 ++++ > include/linux/irqchip/arm-gic-v3.h | 1 + > 2 files changed, 5 insertions(+) > > diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c > index 2988def30972b..a51e8e6a81819 100644 > --- a/drivers/irqchip/irq-gic-v3-its.c > +++ b/drivers/irqchip/irq-gic-v3-its.c > @@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, > int lpi_base; > int nr_lpis; > int nr_ites; > + int id_bits; > int sz; > > if (!its_alloc_device_table(its, dev_id)) > @@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, > /* > * Even if the device wants a single LPI, the ITT must be > * sized as a power of two (and you need at least one bit...). > + * Also honor the ITS's own EID limit. > */ > + id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1; > + nvecs = min_t(unsigned int, nvecs, BIT(id_bits)); > nr_ites = max(2, nvecs); > sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); > sz = max(sz, ITS_ITT_ALIGN); > diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h > index 70c0948f978eb..0225121f30138 100644 > --- a/include/linux/irqchip/arm-gic-v3.h > +++ b/include/linux/irqchip/arm-gic-v3.h > @@ -394,6 +394,7 @@ > #define GITS_TYPER_VLPIS (1UL << 1) > #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4 > #define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4) > +#define GITS_TYPER_IDBITS GENMASK_ULL(12, 8) > #define GITS_TYPER_IDBITS_SHIFT 8 > #define GITS_TYPER_DEVBITS_SHIFT 13 > #define GITS_TYPER_DEVBITS GENMASK_ULL(17, 13)
© 2016 - 2026 Red Hat, Inc.