]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
irqchip/gic-v3-its: Limit number of per-device MSIs to the range the ITS supports
authorMarc Zyngier <maz@kernel.org>
Fri, 6 Feb 2026 15:48:16 +0000 (15:48 +0000)
committerThomas Gleixner <tglx@kernel.org>
Tue, 17 Feb 2026 10:00:43 +0000 (11:00 +0100)
The ITS driver blindly assumes that EventIDs are in abundant supply, to the
point where it never checks how many the hardware 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.

Fixes: 84a6a2e7fc18d ("irqchip: GICv3: ITS: device allocation and configuration")
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Reviewed-by: Zenghui Yu <zenghui.yu@linux.dev>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260206154816.3582887-1-maz@kernel.org
drivers/irqchip/irq-gic-v3-its.c
include/linux/irqchip/arm-gic-v3.h

index 2988def30972b548d13ccaccbe0a9e4338f2959a..a51e8e6a818190c858f4d8e079add7bc57dfe8d4 100644 (file)
@@ -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);
index 70c0948f978eb024627e36ac1dfd0e51fcf1597d..0225121f3013805c46b6547f747835a26bc4d205 100644 (file)
 #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)