Page MenuHomeFreeBSD

D38437.diff
No OneTemporary

D38437.diff

diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -42,6 +42,7 @@
#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 @@
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_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 @@
* - 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 @@
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 @@
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 @@
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

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 25, 12:31 AM (22 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12713146
Default Alt Text
D38437.diff (3 KB)

Event Timeline