git: 248f0cabca75 - main - make maximum interrupt number tunable on ARM, ARM64, MIPS, and RISC-V

Oleksandr Tymoshenko gonzo at FreeBSD.org
Tue Jan 19 00:36:45 UTC 2021


The branch main has been updated by gonzo:

URL: https://cgit.FreeBSD.org/src/commit/?id=248f0cabca75f421553633184b5bf2ffa459d3de

commit 248f0cabca75f421553633184b5bf2ffa459d3de
Author:     Oleksandr Tymoshenko <gonzo at FreeBSD.org>
AuthorDate: 2020-12-30 06:59:03 +0000
Commit:     Oleksandr Tymoshenko <gonzo at FreeBSD.org>
CommitDate: 2021-01-19 00:36:39 +0000

    make maximum interrupt number tunable on ARM, ARM64, MIPS, and RISC-V
    
    Use a machdep.nirq tunable intead of compile-time constant NIRQ
    as a value for maximum number of interrupts. It allows keep a system
    footprint small by default with an option to increase the limit
    for large systems like server-grade ARM64
    
    Reviewd by:     mhorne
    Differential Revision:  https://reviews.freebsd.org/D27844
    Submitted by:   Klara, Inc.
    Sponsored by:   Ampere Computing
---
 sys/arm/arm/genassym.c   |  1 -
 sys/arm/mv/mvreg.h       |  4 ----
 sys/arm64/arm64/gic_v3.c |  3 ++-
 sys/kern/subr_intr.c     | 58 +++++++++++++++++++++++++++++++-----------------
 sys/mips/mips/nexus.c    |  2 +-
 sys/sys/interrupt.h      |  5 -----
 sys/sys/intr.h           |  3 +++
 7 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c
index 39ded845f288..e90bbff6549a 100644
--- a/sys/arm/arm/genassym.c
+++ b/sys/arm/arm/genassym.c
@@ -122,7 +122,6 @@ ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
 ASSYM(MAXCOMLEN, MAXCOMLEN);
 ASSYM(MAXCPU, MAXCPU);
 ASSYM(_NCPUWORDS, _NCPUWORDS);
-ASSYM(NIRQ, NIRQ);
 ASSYM(PCPU_SIZE, sizeof(struct pcpu));
 ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
 ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
diff --git a/sys/arm/mv/mvreg.h b/sys/arm/mv/mvreg.h
index 4ae1e52ee215..95af82b295f6 100644
--- a/sys/arm/mv/mvreg.h
+++ b/sys/arm/mv/mvreg.h
@@ -310,10 +310,6 @@
 #define MV_GPIO_OUT_OPEN_DRAIN		0x2
 #define MV_GPIO_OUT_OPEN_SRC		0x4
 
-#define IS_GPIO_IRQ(irq)	((irq) >= NIRQ && (irq) < NIRQ + MV_GPIO_MAX_NPINS)
-#define GPIO2IRQ(gpio)		((gpio) + NIRQ)
-#define IRQ2GPIO(irq)		((irq) - NIRQ)
-
 #if defined(SOC_MV_ORION)
 #define SAMPLE_AT_RESET		0x10
 #elif defined(SOC_MV_KIRKWOOD)
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index a83ef576e30e..f230eb6bbd06 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/smp.h>
+#include <sys/interrupt.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -388,7 +389,7 @@ gic_v3_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
 
 	switch (which) {
 	case GICV3_IVAR_NIRQS:
-		*result = (NIRQ - sc->gic_nirqs) / sc->gic_nchildren;
+		*result = (intr_nirq - sc->gic_nirqs) / sc->gic_nchildren;
 		return (0);
 	case GICV3_IVAR_REDIST:
 		*result = (uintptr_t)sc->gic_redists.pcpu[PCPU_GET(cpuid)];
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
index 8cda3921fc86..7f99d194e971 100644
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <sys/sched.h>
 #include <sys/smp.h>
+#include <sys/sysctl.h>
 #include <sys/vmmeter.h>
 #ifdef HWPMC_HOOKS
 #include <sys/pmckern.h>
@@ -131,7 +132,7 @@ static struct intr_pic *pic_lookup(device_t dev, intptr_t xref, int flags);
 
 /* Interrupt source definition. */
 static struct mtx isrc_table_lock;
-static struct intr_irqsrc *irq_sources[NIRQ];
+static struct intr_irqsrc **irq_sources;
 u_int irq_next_free;
 
 #ifdef SMP
@@ -142,21 +143,15 @@ static bool irq_assign_cpu = false;
 #endif
 #endif
 
-/*
- * - 2 counters for each I/O interrupt.
- * - MAXCPU counters for each IPI counters for SMP.
- */
-#ifdef SMP
-#define INTRCNT_COUNT   (NIRQ * 2 + INTR_IPI_COUNT * MAXCPU)
-#else
-#define INTRCNT_COUNT   (NIRQ * 2)
-#endif
+int intr_nirq = NIRQ;
+SYSCTL_UINT(_machdep, OID_AUTO, nirq, CTLFLAG_RDTUN, &intr_nirq, 0,
+    "Number of IRQs");
 
 /* Data for MI statistics reporting. */
-u_long intrcnt[INTRCNT_COUNT];
-char intrnames[INTRCNT_COUNT * INTRNAME_LEN];
-size_t sintrcnt = sizeof(intrcnt);
-size_t sintrnames = sizeof(intrnames);
+u_long *intrcnt;
+char *intrnames;
+size_t sintrcnt;
+size_t sintrnames;
 static u_int intrcnt_index;
 
 static struct intr_irqsrc *intr_map_get_isrc(u_int res_id);
@@ -171,11 +166,30 @@ static void intr_map_copy_map_data(u_int res_id, device_t *dev, intptr_t *xref,
 static void
 intr_irq_init(void *dummy __unused)
 {
+	int intrcnt_count;
 
 	SLIST_INIT(&pic_list);
 	mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
 
 	mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF);
+
+	/*
+	 * - 2 counters for each I/O interrupt.
+	 * - MAXCPU counters for each IPI counters for SMP.
+	 */
+	intrcnt_count = intr_nirq * 2;
+#ifdef SMP
+	intrcnt_count += INTR_IPI_COUNT * MAXCPU;
+#endif
+
+	intrcnt = mallocarray(intrcnt_count, sizeof(u_long), M_INTRNG,
+	    M_WAITOK | M_ZERO);
+	intrnames = mallocarray(intrcnt_count, INTRNAME_LEN, M_INTRNG,
+	    M_WAITOK | M_ZERO);
+	sintrcnt = intrcnt_count * sizeof(u_long);
+	sintrnames = intrcnt_count * INTRNAME_LEN;
+	irq_sources = mallocarray(intr_nirq, sizeof(struct intr_irqsrc*),
+	    M_INTRNG, M_WAITOK | M_ZERO);
 }
 SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL);
 
@@ -391,7 +405,7 @@ isrc_alloc_irq(struct intr_irqsrc *isrc)
 
 	mtx_assert(&isrc_table_lock, MA_OWNED);
 
-	maxirqs = nitems(irq_sources);
+	maxirqs = intr_nirq;
 	if (irq_next_free >= maxirqs)
 		return (ENOSPC);
 
@@ -426,7 +440,7 @@ isrc_free_irq(struct intr_irqsrc *isrc)
 
 	mtx_assert(&isrc_table_lock, MA_OWNED);
 
-	if (isrc->isrc_irq >= nitems(irq_sources))
+	if (isrc->isrc_irq >= intr_nirq)
 		return (EINVAL);
 	if (irq_sources[isrc->isrc_irq] != isrc)
 		return (EINVAL);
@@ -1229,7 +1243,7 @@ intr_irq_shuffle(void *arg __unused)
 
 	mtx_lock(&isrc_table_lock);
 	irq_assign_cpu = true;
-	for (i = 0; i < NIRQ; i++) {
+	for (i = 0; i < intr_nirq; i++) {
 		isrc = irq_sources[i];
 		if (isrc == NULL || isrc->isrc_handlers == 0 ||
 		    isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI))
@@ -1529,7 +1543,7 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
 	u_long num;
 	struct intr_irqsrc *isrc;
 
-	for (irqsum = 0, i = 0; i < NIRQ; i++) {
+	for (irqsum = 0, i = 0; i < intr_nirq; i++) {
 		isrc = irq_sources[i];
 		if (isrc == NULL)
 			continue;
@@ -1561,8 +1575,8 @@ struct intr_map_entry
 };
 
 /* XXX Convert irq_map[] to dynamicaly expandable one. */
-static struct intr_map_entry *irq_map[2 * NIRQ];
-static int irq_map_count = nitems(irq_map);
+static struct intr_map_entry **irq_map;
+static int irq_map_count;
 static int irq_map_first_free_idx;
 static struct mtx irq_map_lock;
 
@@ -1712,5 +1726,9 @@ intr_map_init(void *dummy __unused)
 {
 
 	mtx_init(&irq_map_lock, "intr map table", NULL, MTX_DEF);
+
+	irq_map_count = 2 * intr_nirq;
+	irq_map = mallocarray(irq_map_count, sizeof(struct intr_map_entry*),
+	    M_INTRNG, M_WAITOK | M_ZERO);
 }
 SYSINIT(intr_map_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_map_init, NULL);
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index 43b94e239e41..46e7f1831029 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -77,7 +77,7 @@ __FBSDID("$FreeBSD$");
 #endif  /* NEXUS_DEBUG */
 
 #ifdef INTRNG
-#define	NUM_MIPS_IRQS	NIRQ	/* Any INTRNG-mapped IRQ */
+#define	NUM_MIPS_IRQS	intr_nirq	/* Any INTRNG-mapped IRQ */
 #else
 #define	NUM_MIPS_IRQS	6	/* HW IRQs only */
 #endif
diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h
index 138e99495af2..f1770fe64b0b 100644
--- a/sys/sys/interrupt.h
+++ b/sys/sys/interrupt.h
@@ -157,13 +157,8 @@ extern struct	intr_event *tty_intr_event;
 extern void	*vm_ih;
 
 /* Counts and names for statistics (defined in MD code). */
-#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__)
 extern u_long 	*intrcnt;	/* counts for for each device and stray */
 extern char 	*intrnames;	/* string table containing device names */
-#else
-extern u_long 	intrcnt[];	/* counts for for each device and stray */
-extern char 	intrnames[];	/* string table containing device names */
-#endif
 extern size_t	sintrcnt;	/* size of intrcnt table */
 extern size_t	sintrnames;	/* size of intrnames table */
 
diff --git a/sys/sys/intr.h b/sys/sys/intr.h
index 5e305e719e10..c922b10f3368 100644
--- a/sys/sys/intr.h
+++ b/sys/sys/intr.h
@@ -164,4 +164,7 @@ intr_ipi_increment_count(u_long *counter, u_int cpu)
 u_long * intr_ipi_setup_counters(const char *name);
 
 #endif
+
+extern int	intr_nirq;	/* number of IRQs on intrng platforms */
+
 #endif	/* _SYS_INTR_H */


More information about the dev-commits-src-all mailing list