Skip to content

Commit 6c31e12

Browse files
Shanker DonthineniMarc Zyngier
authored andcommitted
irqchip/gic-v3-its: Don't assume GICv3 hardware supports 16bit INTID
The current ITS driver is assuming every ITS hardware implementation supports minimum of 16bit INTID. But this is not true, as per GICv3 specification, INTID field is IMPLEMENTATION DEFINED in the range of 14-24 bits. We might see an unpredictable system behavior on systems where hardware support less than 16bits and software tries to use 64K LPI interrupts. On Qualcomm Datacenter Technologies QDF2400 platform, boot log shows confusing information about number of LPI chunks as shown below. The QDF2400 ITS hardware supports 24bit INTID. This patch allocates the memory resources for PEND/PROP tables based on discoverable value which is specified in GITS_TYPER.IDbits. Also it fixes the log message that reflects the correct number of LPI chunks were allocated. ITS@0xff7efe0000: allocated 524288 Devices @3c0400000 (indirect, esz 8, psz 64K, shr 1) ITS@0xff7efe0000: allocated 8192 Interrupt Collections @3c0130000 (flat, esz 8, psz 64K, shr 1) ITS@0xff7efe0000: allocated 8192 Virtual CPUs @3c0140000 (flat, esz 8, psz 64K, shr 1) ITS: Allocated 524032 chunks for LPIs PCI/MSI: ITS@0xff7efe0000 domain created Platform MSI: ITS@0xff7efe0000 domain created Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent dbd2b82 commit 6c31e12

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

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

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -691,9 +691,11 @@ static struct irq_chip its_irq_chip = {
691691
*/
692692
#define IRQS_PER_CHUNK_SHIFT 5
693693
#define IRQS_PER_CHUNK (1 << IRQS_PER_CHUNK_SHIFT)
694+
#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */
694695

695696
static unsigned long *lpi_bitmap;
696697
static u32 lpi_chunks;
698+
static u32 lpi_id_bits;
697699
static DEFINE_SPINLOCK(lpi_lock);
698700

699701
static int its_lpi_to_chunk(int lpi)
@@ -789,24 +791,21 @@ static void its_lpi_free(struct event_lpi_map *map)
789791
}
790792

791793
/*
792-
* We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
794+
* We allocate memory for PROPBASE to cover 2 ^ lpi_id_bits LPIs to
793795
* deal with (one configuration byte per interrupt). PENDBASE has to
794796
* be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
795797
*/
796-
#define LPI_PROPBASE_SZ SZ_64K
797-
#define LPI_PENDBASE_SZ (LPI_PROPBASE_SZ / 8 + SZ_1K)
798-
799-
/*
800-
* This is how many bits of ID we need, including the useless ones.
801-
*/
802-
#define LPI_NRBITS ilog2(LPI_PROPBASE_SZ + SZ_8K)
798+
#define LPI_NRBITS lpi_id_bits
799+
#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
800+
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
803801

804802
#define LPI_PROP_DEFAULT_PRIO 0xa0
805803

806804
static int __init its_alloc_lpi_tables(void)
807805
{
808806
phys_addr_t paddr;
809807

808+
lpi_id_bits = min_t(u32, gic_rdists->id_bits, ITS_MAX_LPI_NRBITS);
810809
gic_rdists->prop_page = alloc_pages(GFP_NOWAIT,
811810
get_order(LPI_PROPBASE_SZ));
812811
if (!gic_rdists->prop_page) {
@@ -825,7 +824,7 @@ static int __init its_alloc_lpi_tables(void)
825824
/* Make sure the GIC will observe the written configuration */
826825
gic_flush_dcache_to_poc(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
827826

828-
return 0;
827+
return its_lpi_init(lpi_id_bits);
829828
}
830829

831830
static const char *its_base_type_string[] = {
@@ -1100,7 +1099,7 @@ static void its_cpu_init_lpis(void)
11001099
* hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
11011100
*/
11021101
pend_page = alloc_pages(GFP_NOWAIT | __GFP_ZERO,
1103-
get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
1102+
get_order(max_t(u32, LPI_PENDBASE_SZ, SZ_64K)));
11041103
if (!pend_page) {
11051104
pr_err("Failed to allocate PENDBASE for CPU%d\n",
11061105
smp_processor_id());
@@ -1975,8 +1974,5 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
19751974
}
19761975

19771976
gic_rdists = rdists;
1978-
its_alloc_lpi_tables();
1979-
its_lpi_init(rdists->id_bits);
1980-
1981-
return 0;
1977+
return its_alloc_lpi_tables();
19821978
}

0 commit comments

Comments
 (0)