From owner-svn-src-head@freebsd.org Thu Mar 24 09:55:12 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D462EAD8F29; Thu, 24 Mar 2016 09:55:12 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A5617170B; Thu, 24 Mar 2016 09:55:12 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u2O9tBtU043108; Thu, 24 Mar 2016 09:55:11 GMT (envelope-from skra@FreeBSD.org) Received: (from skra@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u2O9tBVT043100; Thu, 24 Mar 2016 09:55:11 GMT (envelope-from skra@FreeBSD.org) Message-Id: <201603240955.u2O9tBVT043100@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: skra set sender to skra@FreeBSD.org using -f From: Svatopluk Kraus Date: Thu, 24 Mar 2016 09:55:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297230 - in head/sys: arm/arm arm/include kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Mar 2016 09:55:12 -0000 Author: skra Date: Thu Mar 24 09:55:11 2016 New Revision: 297230 URL: https://svnweb.freebsd.org/changeset/base/297230 Log: Generalize IPI support for ARM intrng and use it for interrupt controller IPI provider. New struct intr_ipi is defined which keeps all info about an IPI: its name, counter, send and dispatch methods. Generic intr_ipi_setup(), intr_ipi_send() and intr_ipi_dispatch() functions are implemented. An IPI provider must implement two functions: (1) an intr_ipi_send_t function which is able to send an IPI, (2) a setup function which initializes itself for an IPI and calls intr_ipi_setup() with appropriate arguments. Differential Revision: https://reviews.freebsd.org/D5700 Modified: head/sys/arm/arm/gic.c head/sys/arm/arm/machdep_intr.c head/sys/arm/arm/mp_machdep.c head/sys/arm/include/intr.h head/sys/arm/include/smp.h head/sys/kern/pic_if.m head/sys/kern/subr_intr.c head/sys/sys/intr.h Modified: head/sys/arm/arm/gic.c ============================================================================== --- head/sys/arm/arm/gic.c Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/arm/arm/gic.c Thu Mar 24 09:55:11 2016 (r297230) @@ -121,6 +121,11 @@ __FBSDID("$FreeBSD$"); 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 @@ dispatch_irq: #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 @@ arm_gic_ipi_send(device_t dev, struct in 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 @@ static device_method_t arm_gic_methods[] 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 } Modified: head/sys/arm/arm/machdep_intr.c ============================================================================== --- head/sys/arm/arm/machdep_intr.c Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/arm/arm/machdep_intr.c Thu Mar 24 09:55:11 2016 (r297230) @@ -64,8 +64,19 @@ __FBSDID("$FreeBSD$"); #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 @@ arm_irq_memory_barrier(uintptr_t irq) #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 @@ intr_ipi_lookup(u_int ipi) 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 Modified: head/sys/arm/arm/mp_machdep.c ============================================================================== --- head/sys/arm/arm/mp_machdep.c Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/arm/arm/mp_machdep.c Thu Mar 24 09:55:11 2016 (r297230) @@ -429,12 +429,11 @@ release_aps(void *dummy __unused) 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 @@ ipi_all_but_self(u_int ipi) 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 @@ ipi_cpu(int cpu, u_int ipi) 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 @@ ipi_selected(cpuset_t cpus, u_int ipi) { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); +#ifdef ARM_INTRNG + intr_ipi_send(cpus, ipi); +#else pic_ipi_send(cpus, ipi); +#endif } - Modified: head/sys/arm/include/intr.h ============================================================================== --- head/sys/arm/include/intr.h Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/arm/include/intr.h Thu Mar 24 09:55:11 2016 (r297230) @@ -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? */ Modified: head/sys/arm/include/smp.h ============================================================================== --- head/sys/arm/include/smp.h Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/arm/include/smp.h Thu Mar 24 09:55:11 2016 (r297230) @@ -37,8 +37,8 @@ void ipi_cpu(int cpu, u_int ipi); 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 Modified: head/sys/kern/pic_if.m ============================================================================== --- head/sys/kern/pic_if.m Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/kern/pic_if.m Thu Mar 24 09:55:11 2016 (r297230) @@ -60,6 +60,13 @@ CODE { { 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 @@ METHOD void ipi_send { 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; Modified: head/sys/kern/subr_intr.c ============================================================================== --- head/sys/kern/subr_intr.c Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/kern/subr_intr.c Thu Mar 24 09:55:11 2016 (r297230) @@ -311,8 +311,8 @@ intr_irq_dispatch(struct intr_irqsrc *is /* * 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 @@ isrc_alloc(u_int type, u_int extsize) /* * 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 @@ intr_namespace_map_irq(device_t dev, uin 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 @@ intr_fdt_map_irq(phandle_t node, pcell_t 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 */ } Modified: head/sys/sys/intr.h ============================================================================== --- head/sys/sys/intr.h Thu Mar 24 09:35:29 2016 (r297229) +++ head/sys/sys/intr.h Thu Mar 24 09:55:11 2016 (r297230) @@ -50,8 +50,6 @@ typedef int intr_irq_filter_t(void *arg) #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_irqsrc { 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);