Index: head/sys/arm/arm/gic.c =================================================================== --- head/sys/arm/arm/gic.c +++ head/sys/arm/arm/gic.c @@ -121,6 +121,11 @@ static u_int gic_irq_cpu; static int arm_gic_intr(void *); static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc); + +#ifdef SMP +u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1]; +#define ISRC_IPI(isrc) sgi_to_ipi[isrc->isrc_data - GIC_FIRST_SGI] +#endif #endif struct arm_gic_softc { @@ -562,7 +567,7 @@ #ifdef SMP /* Call EOI for all IPI before dispatch. */ gic_c_write_4(sc, GICC_EOIR, irq_active_reg); - intr_ipi_dispatch(isrc, tf); + intr_ipi_dispatch(ISRC_IPI(isrc), tf); goto next_irq; #else device_printf(sc->gic_dev, "SGI %u on UP system detected\n", @@ -918,6 +923,20 @@ gic_d_write_4(sc, GICD_SGIR(0), val | irq); } + +static int +arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc *isrc) +{ + struct arm_gic_softc *sc = device_get_softc(dev); + u_int irq; + int error; + + error = gic_map_nspc(sc, isrc, &irq); + if (error != 0) + return (error); + sgi_to_ipi[irq - GIC_FIRST_SGI] = ipi; + return (0); +} #endif #else static int @@ -1146,6 +1165,7 @@ DEVMETHOD(pic_bind, arm_gic_bind), DEVMETHOD(pic_init_secondary, arm_gic_init_secondary), DEVMETHOD(pic_ipi_send, arm_gic_ipi_send), + DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup), #endif #endif { 0, 0 } Index: head/sys/arm/arm/machdep_intr.c =================================================================== --- head/sys/arm/arm/machdep_intr.c +++ head/sys/arm/arm/machdep_intr.c @@ -64,8 +64,19 @@ #include "pic_if.h" #ifdef SMP -static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT]; -static u_int ipi_next_num; +#define INTR_IPI_NAMELEN (MAXCOMLEN + 1) + +struct intr_ipi { + intr_ipi_handler_t * ii_handler; + void * ii_handler_arg; + intr_ipi_send_t * ii_send; + void * ii_send_arg; + char ii_name[INTR_IPI_NAMELEN]; + u_long * ii_count; +}; + +static struct intr_ipi ipi_sources[INTR_IPI_COUNT]; +u_int ipi_next_num; #endif #endif @@ -134,10 +145,7 @@ #ifdef ARM_INTRNG #ifdef SMP -/* - * Lookup IPI source. - */ -static struct intr_irqsrc * +static inline struct intr_ipi * intr_ipi_lookup(u_int ipi) { @@ -147,112 +155,97 @@ return (&ipi_sources[ipi]); } -/* - * interrupt controller dispatch function for IPIs. It should - * be called straight from the interrupt controller, when associated - * interrupt source is learned. Or from anybody who has an interrupt - * source mapped. - */ void -intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf) +intr_ipi_dispatch(u_int ipi, struct trapframe *tf) { void *arg; + struct intr_ipi *ii; - KASSERT(isrc != NULL, ("%s: no source", __func__)); + ii = intr_ipi_lookup(ipi); + if (ii->ii_count == NULL) + panic("%s: not setup IPI %u", __func__, ipi); - intr_ipi_increment_count(isrc->isrc_count, PCPU_GET(cpuid)); + intr_ipi_increment_count(ii->ii_count, PCPU_GET(cpuid)); /* * Supply ipi filter with trapframe argument * if none is registered. */ - arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf; - isrc->isrc_ipifilter(arg); + arg = ii->ii_handler_arg != NULL ? ii->ii_handler_arg : tf; + ii->ii_handler(arg); } -/* - * Map IPI into interrupt controller. - * - * Not SMP coherent. - */ -static int -ipi_map(struct intr_irqsrc *isrc, u_int ipi) +void +intr_ipi_send(cpuset_t cpus, u_int ipi) { - boolean_t is_percpu; - int error; + struct intr_ipi *ii; - if (ipi >= INTR_IPI_COUNT) - panic("%s: no such IPI %u", __func__, ipi); + ii = intr_ipi_lookup(ipi); + if (ii->ii_count == NULL) + panic("%s: not setup IPI %u", __func__, ipi); - KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__)); + ii->ii_send(ii->ii_send_arg, cpus); +} - isrc->isrc_type = INTR_ISRCT_NAMESPACE; - isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI; - isrc->isrc_nspc_num = ipi_next_num; +void +intr_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand, + void *h_arg, intr_ipi_send_t *send, void *s_arg) +{ + struct intr_ipi *ii; + + ii = intr_ipi_lookup(ipi); - error = PIC_REGISTER(intr_irq_root_dev, isrc, &is_percpu); - if (error == 0) { - isrc->isrc_dev = intr_irq_root_dev; - ipi_next_num++; - } - return (error); + KASSERT(hand != NULL, ("%s: ipi %u no handler", __func__, ipi)); + KASSERT(send != NULL, ("%s: ipi %u no sender", __func__, ipi)); + KASSERT(ii->ii_count == NULL, ("%s: ipi %u reused", __func__, ipi)); + + ii->ii_handler = hand; + ii->ii_handler_arg = h_arg; + ii->ii_send = send; + ii->ii_send_arg = s_arg; + strlcpy(ii->ii_name, name, INTR_IPI_NAMELEN); + ii->ii_count = intr_ipi_setup_counters(name); } /* - * Setup IPI handler to interrupt source. - * - * Note that there could be more ways how to send and receive IPIs - * on a platform like fast interrupts for example. In that case, - * one can call this function with ASIF_NOALLOC flag set and then - * call intr_ipi_dispatch() when appropriate. - * - * Not SMP coherent. + * Send IPI thru interrupt controller. */ -int -intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, - void *arg, u_int flags) +static void +pic_ipi_send(void *arg, cpuset_t cpus) { - struct intr_irqsrc *isrc; - int error; - - if (filter == NULL) - return(EINVAL); - - isrc = intr_ipi_lookup(ipi); - if (isrc->isrc_ipifilter != NULL) - return (EEXIST); - - if ((flags & AISHF_NOALLOC) == 0) { - error = ipi_map(isrc, ipi); - if (error != 0) - return (error); - } - - isrc->isrc_ipifilter = filter; - isrc->isrc_arg = arg; - isrc->isrc_handlers = 1; - isrc->isrc_count = intr_ipi_setup_counters(name); - isrc->isrc_index = 0; /* it should not be used in IPI case */ - if (isrc->isrc_dev != NULL) { - PIC_ENABLE_INTR(isrc->isrc_dev, isrc); - PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc); - } - return (0); + KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__)); + PIC_IPI_SEND(intr_irq_root_dev, arg, cpus); } /* - * Send IPI thru interrupt controller. + * Setup IPI handler on interrupt controller. + * + * Not SMP coherent. */ -void -pic_ipi_send(cpuset_t cpus, u_int ipi) +int +intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand, + void *arg) { + int error; struct intr_irqsrc *isrc; - isrc = intr_ipi_lookup(ipi); - KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__)); - PIC_IPI_SEND(intr_irq_root_dev, isrc, cpus); + + isrc = intr_isrc_alloc(INTR_ISRCT_NAMESPACE, 0); + isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI; + isrc->isrc_nspc_num = ipi_next_num; + + error = PIC_IPI_SETUP(intr_irq_root_dev, ipi, isrc); + if (error != 0) + return (error); + + ipi_next_num++; + + isrc->isrc_dev = intr_irq_root_dev; + isrc->isrc_handlers = 1; + intr_ipi_setup(ipi, name, hand, arg, pic_ipi_send, isrc); + return (0); } #endif #endif Index: head/sys/arm/arm/mp_machdep.c =================================================================== --- head/sys/arm/arm/mp_machdep.c +++ head/sys/arm/arm/mp_machdep.c @@ -429,12 +429,11 @@ return; #ifdef ARM_INTRNG - intr_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0); - intr_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0); - intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0); - intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0); - intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0); - + intr_pic_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL); + intr_pic_ipi_setup(IPI_AST, "ast", ipi_ast, NULL); + intr_pic_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL); + intr_pic_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL); + intr_pic_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL); #else #ifdef IPI_IRQ_START start = IPI_IRQ_START; @@ -502,7 +501,11 @@ other_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &other_cpus); CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); +#ifdef ARM_INTRNG + intr_ipi_send(other_cpus, ipi); +#else pic_ipi_send(other_cpus, ipi); +#endif } void @@ -514,7 +517,11 @@ CPU_SET(cpu, &cpus); CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi); +#ifdef ARM_INTRNG + intr_ipi_send(cpus, ipi); +#else pic_ipi_send(cpus, ipi); +#endif } void @@ -522,6 +529,9 @@ { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); +#ifdef ARM_INTRNG + intr_ipi_send(cpus, ipi); +#else pic_ipi_send(cpus, ipi); +#endif } - Index: head/sys/arm/include/intr.h =================================================================== --- head/sys/arm/include/intr.h +++ head/sys/arm/include/intr.h @@ -52,14 +52,17 @@ #include #ifdef SMP -void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); +typedef void intr_ipi_send_t(void *, cpuset_t); +typedef void intr_ipi_handler_t(void *); -#define AISHF_NOALLOC 0x0001 +void intr_ipi_dispatch(u_int, struct trapframe *); +void intr_ipi_send(cpuset_t, u_int); -int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, - void *arg, u_int flags); -#endif +void intr_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *, + intr_ipi_send_t *, void *); +int intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *); +#endif #else /* ARM_INTRNG */ /* XXX move to std.* files? */ Index: head/sys/arm/include/smp.h =================================================================== --- head/sys/arm/include/smp.h +++ head/sys/arm/include/smp.h @@ -37,8 +37,8 @@ void ipi_selected(cpuset_t cpus, u_int ipi); /* PIC interface */ -void pic_ipi_send(cpuset_t cpus, u_int ipi); #ifndef ARM_INTRNG +void pic_ipi_send(cpuset_t cpus, u_int ipi); void pic_ipi_clear(int ipi); int pic_ipi_read(int arg); #endif Index: head/sys/kern/pic_if.m =================================================================== --- head/sys/kern/pic_if.m +++ head/sys/kern/pic_if.m @@ -60,6 +60,13 @@ { return; } + + static int + dflt_pic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc *isrc) + { + + return (EOPNOTSUPP); + } }; METHOD int register { @@ -122,3 +129,9 @@ struct intr_irqsrc *isrc; cpuset_t cpus; } DEFAULT null_pic_ipi_send; + +METHOD int ipi_setup { + device_t dev; + u_int ipi; + struct intr_irqsrc *isrc; +} DEFAULT dflt_pic_ipi_setup; Index: head/sys/kern/subr_intr.c =================================================================== --- head/sys/kern/subr_intr.c +++ head/sys/kern/subr_intr.c @@ -311,8 +311,8 @@ /* * Allocate interrupt source. */ -static struct intr_irqsrc * -isrc_alloc(u_int type, u_int extsize) +struct intr_irqsrc * +intr_isrc_alloc(u_int type, u_int extsize) { struct intr_irqsrc *isrc; @@ -329,8 +329,8 @@ /* * Free interrupt source. */ -static void -isrc_free(struct intr_irqsrc *isrc) +void +intr_isrc_free(struct intr_irqsrc *isrc) { free(isrc, M_INTRNG); @@ -462,20 +462,20 @@ struct intr_irqsrc *isrc, *new_isrc; int error; - new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0); + new_isrc = intr_isrc_alloc(INTR_ISRCT_NAMESPACE, 0); mtx_lock(&isrc_table_lock); isrc = isrc_namespace_lookup(dev, type, num); if (isrc != NULL) { mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); + intr_isrc_free(new_isrc); return (isrc->isrc_irq); /* already mapped */ } error = isrc_alloc_irq_locked(new_isrc); if (error != 0) { mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); + intr_isrc_free(new_isrc); return (IRQ_INVALID); /* no space left */ } @@ -526,20 +526,20 @@ xref = (intptr_t)node; /* It's so simple for now. */ cellsize = ncells * sizeof(*cells); - new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize); + new_isrc = intr_isrc_alloc(INTR_ISRCT_FDT, cellsize); mtx_lock(&isrc_table_lock); isrc = isrc_fdt_lookup(xref, cells, ncells); if (isrc != NULL) { mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); + intr_isrc_free(new_isrc); return (isrc->isrc_irq); /* already mapped */ } error = isrc_alloc_irq_locked(new_isrc); if (error != 0) { mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); + intr_isrc_free(new_isrc); return (IRQ_INVALID); /* no space left */ } Index: head/sys/sys/intr.h =================================================================== --- head/sys/sys/intr.h +++ head/sys/sys/intr.h @@ -50,8 +50,6 @@ #define INTR_ISRC_NAMELEN (MAXCOMLEN + 1) -typedef void intr_ipi_filter_t(void *arg); - enum intr_isrc_type { INTR_ISRCT_NAMESPACE, INTR_ISRCT_FDT @@ -81,15 +79,17 @@ struct intr_event * isrc_event; #ifdef INTR_SOLO intr_irq_filter_t * isrc_filter; -#endif - intr_ipi_filter_t * isrc_ipifilter; void * isrc_arg; +#endif #ifdef FDT u_int isrc_ncells; pcell_t isrc_cells[]; /* leave it last */ #endif }; +struct intr_irqsrc *intr_isrc_alloc(u_int type, u_int extsize); +void intr_isrc_free(struct intr_irqsrc *isrc); + void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...) __printflike(2, 3);