git: 28137bdb19aa - main - intrng: track counter allocation with a bitmap
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 14 Feb 2023 18:23:54 UTC
The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=28137bdb19aa34b8351108de4257795a93c0ba09 commit 28137bdb19aa34b8351108de4257795a93c0ba09 Author: Mitchell Horne <mhorne@FreeBSD.org> AuthorDate: 2023-02-14 18:02:12 +0000 Commit: Mitchell Horne <mhorne@FreeBSD.org> CommitDate: 2023-02-14 18:06:00 +0000 intrng: track counter allocation with a bitmap Crucially, this allows releasing counters, and interrupt sources by extension. Where before we were incrementing intrcnt_index with atomics, now we protect the bitmap using the existing isrc_table_lock mutex. Reviewed by: mmel MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D38437 --- sys/kern/subr_intr.c | 54 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 96a319b3c8b4..a95d2adbed04 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/bus.h> #include <sys/conf.h> #include <sys/cpuset.h> @@ -152,7 +153,8 @@ u_long *intrcnt; char *intrnames; size_t sintrcnt; size_t sintrnames; -static u_int intrcnt_index; +int nintrcnt; +static bitstr_t *intrcnt_bitmap; static struct intr_irqsrc *intr_map_get_isrc(u_int res_id); static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc); @@ -166,7 +168,6 @@ 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) { - u_int intrcnt_count; SLIST_INIT(&pic_list); mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); @@ -177,17 +178,21 @@ intr_irq_init(void *dummy __unused) * - 2 counters for each I/O interrupt. * - MAXCPU counters for each IPI counters for SMP. */ - intrcnt_count = intr_nirq * 2; + nintrcnt = intr_nirq * 2; #ifdef SMP - intrcnt_count += INTR_IPI_COUNT * MAXCPU; + nintrcnt += INTR_IPI_COUNT * MAXCPU; #endif - intrcnt = mallocarray(intrcnt_count, sizeof(u_long), M_INTRNG, + intrcnt = mallocarray(nintrcnt, sizeof(u_long), M_INTRNG, M_WAITOK | M_ZERO); - intrnames = mallocarray(intrcnt_count, INTRNAME_LEN, M_INTRNG, + intrnames = mallocarray(nintrcnt, INTRNAME_LEN, M_INTRNG, M_WAITOK | M_ZERO); - sintrcnt = intrcnt_count * sizeof(u_long); - sintrnames = intrcnt_count * INTRNAME_LEN; + sintrcnt = nintrcnt * sizeof(u_long); + sintrnames = nintrcnt * INTRNAME_LEN; + + /* Allocate the bitmap tracking counter allocations. */ + intrcnt_bitmap = bit_alloc(nintrcnt, M_INTRNG, M_WAITOK | M_ZERO); + irq_sources = mallocarray(intr_nirq, sizeof(struct intr_irqsrc*), M_INTRNG, M_WAITOK | M_ZERO); } @@ -266,13 +271,17 @@ isrc_update_name(struct intr_irqsrc *isrc, const char *name) static void isrc_setup_counters(struct intr_irqsrc *isrc) { - u_int index; + int index; + + mtx_assert(&isrc_table_lock, MA_OWNED); /* - * XXX - it does not work well with removable controllers and - * interrupt sources !!! + * Allocate two counter values, the second tracking "stray" interrupts. */ - index = atomic_fetchadd_int(&intrcnt_index, 2); + bit_ffc_area(intrcnt_bitmap, nintrcnt, 2, &index); + if (index == -1) + panic("Failed to allocate 2 counters. Array exhausted?"); + bit_nset(intrcnt_bitmap, index, index + 1); isrc->isrc_index = index; isrc->isrc_count = &intrcnt[index]; isrc_update_name(isrc, NULL); @@ -284,8 +293,11 @@ isrc_setup_counters(struct intr_irqsrc *isrc) static void isrc_release_counters(struct intr_irqsrc *isrc) { + int idx = isrc->isrc_index; - panic("%s: not implemented", __func__); + mtx_assert(&isrc_table_lock, MA_OWNED); + + bit_nclear(intrcnt_bitmap, idx, idx + 1); } #ifdef SMP @@ -298,11 +310,25 @@ intr_ipi_setup_counters(const char *name) u_int index, i; char str[INTRNAME_LEN]; - index = atomic_fetchadd_int(&intrcnt_index, MAXCPU); + mtx_lock(&isrc_table_lock); + + /* + * We should never have a problem finding MAXCPU contiguous counters, + * in practice. Interrupts will be allocated sequentially during boot, + * so the array should fill from low to high index. Once reserved, the + * IPI counters will never be released. Similarly, we will not need to + * allocate more IPIs once the system is running. + */ + bit_ffc_area(intrcnt_bitmap, nintrcnt, MAXCPU, &index); + if (index == -1) + panic("Failed to allocate %d counters. Array exhausted?", + MAXCPU); + bit_nset(intrcnt_bitmap, index, index + MAXCPU - 1); for (i = 0; i < MAXCPU; i++) { snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name); intrcnt_setname(str, index + i); } + mtx_unlock(&isrc_table_lock); return (&intrcnt[index]); } #endif