diff --git a/sys/arm/mv/mv_ap806_gicp.c b/sys/arm/mv/mv_ap806_gicp.c --- a/sys/arm/mv/mv_ap806_gicp.c +++ b/sys/arm/mv/mv_ap806_gicp.c @@ -391,7 +391,7 @@ for (i = 0; i < count; i++) { BIT_SET(sc->msi_bitmap_size, - mv_ap806_gicp_irq_to_msi(sc, srcs[i]->isrc_irq), + mv_ap806_gicp_irq_to_msi(sc, srcs[i]->isrc_event->ie_irq), sc->msi_bitmap); } @@ -407,7 +407,7 @@ sc = device_get_softc(dev); *addr = rman_get_start(sc->res); - *data = mv_ap806_gicp_irq_to_msi(sc, isrc->isrc_irq); + *data = mv_ap806_gicp_irq_to_msi(sc, isrc->isrc_event->ie_irq); return (0); } diff --git a/sys/arm/mv/mv_ap806_sei.c b/sys/arm/mv/mv_ap806_sei.c --- a/sys/arm/mv/mv_ap806_sei.c +++ b/sys/arm/mv/mv_ap806_sei.c @@ -451,7 +451,7 @@ for (i = 0; i < count; i++) { BIT_SET(MV_AP806_SEI_CP_SIZE, - srcs[i]->isrc_irq - MV_AP806_SEI_CP_FIRST, + srcs[i]->isrc_event->ie_irq - MV_AP806_SEI_CP_FIRST, &sc->msi_bitmap); } @@ -467,7 +467,7 @@ sc = device_get_softc(dev); *addr = rman_get_start(sc->mem_res) + MV_AP806_SEI_SETSPI_OFFSET; - *data = isrc->isrc_irq; + *data = isrc->isrc_event->ie_irq; return (0); } 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 @@ -415,6 +415,133 @@ return (EINVAL); } +/* + * Interrupt source pre_ithread method for MI interrupt framework. + */ +static void +intr_isrc_pre_ithread(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_PRE_ITHREAD(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source post_ithread method for MI interrupt framework. + */ +static void +intr_isrc_post_ithread(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_POST_ITHREAD(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source post_filter method for MI interrupt framework. + */ +static void +intr_isrc_post_filter(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_POST_FILTER(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source assign_cpu method for MI interrupt framework. + */ +static int +intr_isrc_assign_cpu(void *arg, int cpu) +{ +#ifdef SMP + struct intr_irqsrc *isrc = arg; + int error; + + mtx_lock(&isrc_table_lock); + if (cpu == NOCPU) { + CPU_ZERO(&isrc->isrc_cpu); + isrc->isrc_flags &= ~INTR_ISRCF_BOUND; + } else { + CPU_SETOF(cpu, &isrc->isrc_cpu); + isrc->isrc_flags |= INTR_ISRCF_BOUND; + } + + /* + * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or + * re-balance it to another CPU or enable it on more CPUs. However, + * PIC is expected to change isrc_cpu appropriately to keep us well + * informed if the call is successful. + */ + if (irq_assign_cpu) { + error = PIC_BIND_INTR(isrc->isrc_dev, isrc); + if (error) { + CPU_ZERO(&isrc->isrc_cpu); + mtx_unlock(&isrc_table_lock); + return (error); + } + } + mtx_unlock(&isrc_table_lock); + return (0); +#else + return (EOPNOTSUPP); +#endif +} + +/* + * Create interrupt event for interrupt source. + */ +static int +isrc_event_create(struct intr_irqsrc *isrc) +{ + struct intr_event *ie; + int error; + + error = intr_event_create(&ie, isrc, 0, INTR_IRQ_INVALID, + intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter, + intr_isrc_assign_cpu, "%s:", isrc->isrc_name); + if (error) + return (error); + + mtx_lock(&isrc_table_lock); + /* + * Make sure that we do not mix the two ways + * how we handle interrupt sources. Let contested event wins. + */ +#ifdef INTR_SOLO + if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { +#else + if (isrc->isrc_event != NULL) { +#endif + mtx_unlock(&isrc_table_lock); + intr_event_destroy(ie); + return (isrc->isrc_event != NULL ? EBUSY : 0); + } + isrc->isrc_event = ie; + mtx_unlock(&isrc_table_lock); + + return (0); +} + +#ifdef notyet +/* + * Destroy interrupt event for interrupt source. + */ +static void +isrc_event_destroy(struct intr_irqsrc *isrc) +{ + struct intr_event *ie; + + mtx_lock(&isrc_table_lock); + ie = isrc->isrc_event; + isrc->isrc_event = NULL; + mtx_unlock(&isrc_table_lock); + + if (ie != NULL) + intr_event_destroy(ie); +} +#endif + /* * Alloc unique interrupt number (resource handle) for interrupt source. * @@ -448,7 +575,7 @@ return (ENOSPC); found: - isrc->isrc_irq = irq; + isrc->isrc_event->ie_irq = irq; irq_sources[irq] = isrc; irq_next_free = irq + 1; @@ -466,13 +593,13 @@ mtx_assert(&isrc_table_lock, MA_OWNED); - if (isrc->isrc_irq >= intr_nirq) + if (isrc->isrc_event->ie_irq >= intr_nirq) return (EINVAL); - if (irq_sources[isrc->isrc_irq] != isrc) + if (irq_sources[isrc->isrc_event->ie_irq] != isrc) return (EINVAL); - irq_sources[isrc->isrc_irq] = NULL; - isrc->isrc_irq = INTR_IRQ_INVALID; /* just to be safe */ + irq_sources[isrc->isrc_event->ie_irq] = NULL; + isrc->isrc_event->ie_irq = INTR_IRQ_INVALID; /* just to be safe */ /* * If we are recovering from the state irq_sources table is full, @@ -498,16 +625,20 @@ bzero(isrc, sizeof(struct intr_irqsrc)); isrc->isrc_dev = dev; - isrc->isrc_irq = INTR_IRQ_INVALID; /* just to be safe */ isrc->isrc_flags = flags; va_start(ap, fmt); vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap); va_end(ap); + error = isrc_event_create(isrc); + if (error) + return (error); + mtx_lock(&isrc_table_lock); error = isrc_alloc_irq(isrc); if (error != 0) { + intr_event_destroy(isrc->isrc_event); mtx_unlock(&isrc_table_lock); return (error); } @@ -595,131 +726,6 @@ } #endif -/* - * Interrupt source pre_ithread method for MI interrupt framework. - */ -static void -intr_isrc_pre_ithread(void *arg) -{ - struct intr_irqsrc *isrc = arg; - - PIC_PRE_ITHREAD(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source post_ithread method for MI interrupt framework. - */ -static void -intr_isrc_post_ithread(void *arg) -{ - struct intr_irqsrc *isrc = arg; - - PIC_POST_ITHREAD(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source post_filter method for MI interrupt framework. - */ -static void -intr_isrc_post_filter(void *arg) -{ - struct intr_irqsrc *isrc = arg; - - PIC_POST_FILTER(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source assign_cpu method for MI interrupt framework. - */ -static int -intr_isrc_assign_cpu(void *arg, int cpu) -{ -#ifdef SMP - struct intr_irqsrc *isrc = arg; - int error; - - mtx_lock(&isrc_table_lock); - if (cpu == NOCPU) { - CPU_ZERO(&isrc->isrc_cpu); - isrc->isrc_flags &= ~INTR_ISRCF_BOUND; - } else { - CPU_SETOF(cpu, &isrc->isrc_cpu); - isrc->isrc_flags |= INTR_ISRCF_BOUND; - } - - /* - * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or - * re-balance it to another CPU or enable it on more CPUs. However, - * PIC is expected to change isrc_cpu appropriately to keep us well - * informed if the call is successful. - */ - if (irq_assign_cpu) { - error = PIC_BIND_INTR(isrc->isrc_dev, isrc); - if (error) { - CPU_ZERO(&isrc->isrc_cpu); - mtx_unlock(&isrc_table_lock); - return (error); - } - } - mtx_unlock(&isrc_table_lock); - return (0); -#else - return (EOPNOTSUPP); -#endif -} - -/* - * Create interrupt event for interrupt source. - */ -static int -isrc_event_create(struct intr_irqsrc *isrc) -{ - struct intr_event *ie; - int error; - - error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq, - intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter, - intr_isrc_assign_cpu, "%s:", isrc->isrc_name); - if (error) - return (error); - - mtx_lock(&isrc_table_lock); - /* - * Make sure that we do not mix the two ways - * how we handle interrupt sources. Let contested event wins. - */ -#ifdef INTR_SOLO - if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { -#else - if (isrc->isrc_event != NULL) { -#endif - mtx_unlock(&isrc_table_lock); - intr_event_destroy(ie); - return (isrc->isrc_event != NULL ? EBUSY : 0); - } - isrc->isrc_event = ie; - mtx_unlock(&isrc_table_lock); - - return (0); -} -#ifdef notyet -/* - * Destroy interrupt event for interrupt source. - */ -static void -isrc_event_destroy(struct intr_irqsrc *isrc) -{ - struct intr_event *ie; - - mtx_lock(&isrc_table_lock); - ie = isrc->isrc_event; - isrc->isrc_event = NULL; - mtx_unlock(&isrc_table_lock); - - if (ie != NULL) - intr_event_destroy(ie); -} -#endif /* * Add handler to interrupt source. */ @@ -730,12 +736,6 @@ { int error; - if (isrc->isrc_event == NULL) { - error = isrc_event_create(isrc); - if (error) - return (error); - } - error = intr_event_add_handler(isrc->isrc_event, name, filter, handler, arg, intr_priority(flags), flags, cookiep); if (error == 0) { @@ -1112,7 +1112,8 @@ { error = intr_add_handler(name, isrc, filt, hand, arg, flags, cookiep); - debugf("irq %u add handler error %d on %s\n", isrc->isrc_irq, error, name); + debugf("irq %u add handler error %d on %s\n", + isrc->isrc_event->ie_irq, error, name); } if (error != 0) return (error); diff --git a/sys/sys/intr.h b/sys/sys/intr.h --- a/sys/sys/intr.h +++ b/sys/sys/intr.h @@ -80,7 +80,6 @@ /* Interrupt source definition. */ struct intr_irqsrc { device_t isrc_dev; /* where isrc is mapped */ - u_int isrc_irq; /* unique identificator */ u_int isrc_flags; char isrc_name[INTR_ISRC_NAMELEN]; cpuset_t isrc_cpu; /* on which CPUs is enabled */