Index: sys/kern/subr_intr.c =================================================================== --- sys/kern/subr_intr.c +++ sys/kern/subr_intr.c @@ -153,6 +153,9 @@ size_t sintrcnt; size_t sintrnames; static u_int intrcnt_index; +#ifdef SMP +static u_int intrcnt_ipi_index; +#endif 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); @@ -167,6 +170,7 @@ intr_irq_init(void *dummy __unused) { u_int intrcnt_count; + int i; SLIST_INIT(&pic_list); mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); @@ -179,11 +183,14 @@ */ intrcnt_count = intr_nirq * 2; #ifdef SMP + intrcnt_ipi_index = intrcnt_count; intrcnt_count += INTR_IPI_COUNT * MAXCPU; #endif intrcnt = mallocarray(intrcnt_count, sizeof(u_long), M_INTRNG, M_WAITOK | M_ZERO); + for (i = 0; i < intr_nirq * 2; i += 2) + intrcnt[i] = i + 2; intrnames = mallocarray(intrcnt_count, INTRNAME_LEN, M_INTRNG, M_WAITOK | M_ZERO); sintrcnt = intrcnt_count * sizeof(u_long); @@ -268,13 +275,14 @@ { u_int index; - /* - * XXX - it does not work well with removable controllers and - * interrupt sources !!! - */ - index = atomic_fetchadd_int(&intrcnt_index, 2); + while ((index = atomic_swap_int(&intrcnt_index, ~0)) == ~0); + if (index >= intr_nirq * 2) + panic("%s: interrupt counters exhausted!", __func__); + atomic_store_int(&intrcnt_index, intrcnt[index]); + isrc->isrc_index = index; - isrc->isrc_count = &intrcnt[index]; + isrc->isrc_count = intrcnt + index; + intrcnt[index] = 0; isrc_update_name(isrc, NULL); } @@ -284,8 +292,16 @@ static void isrc_release_counters(struct intr_irqsrc *isrc) { + u_int index, prev; - panic("%s: not implemented", __func__); + index = isrc->isrc_index; + isrc->isrc_count = NULL; + intrcnt[index + 1] = 0; + isrc_update_name(isrc, NULL); + + while ((prev = atomic_swap_int(&intrcnt_index, ~0)) == ~0); + intrcnt[index] = prev; + atomic_store_int(&intrcnt_index, index); } #ifdef SMP @@ -298,7 +314,7 @@ u_int index, i; char str[INTRNAME_LEN]; - index = atomic_fetchadd_int(&intrcnt_index, MAXCPU); + index = atomic_fetchadd_int(&intrcnt_ipi_index, MAXCPU); for (i = 0; i < MAXCPU; i++) { snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name); intrcnt_setname(str, index + i);