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 <sys/intr.h>
 
 #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);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to