svn commit: r276094 - in projects/arm_intrng/sys/arm: arm include

Andrew Turner andrew at FreeBSD.org
Mon Dec 22 22:29:50 UTC 2014


Author: andrew
Date: Mon Dec 22 22:29:48 2014
New Revision: 276094
URL: https://svnweb.freebsd.org/changeset/base/276094

Log:
  Add a patch from ian@ to clean up a the code to get it closer to where
  we could import it into head
  
  Obtained from:	ian

Modified:
  projects/arm_intrng/sys/arm/arm/gic.c
  projects/arm_intrng/sys/arm/arm/intrng.c
  projects/arm_intrng/sys/arm/arm/mp_machdep.c
  projects/arm_intrng/sys/arm/include/intr.h
  projects/arm_intrng/sys/arm/include/smp.h

Modified: projects/arm_intrng/sys/arm/arm/gic.c
==============================================================================
--- projects/arm_intrng/sys/arm/arm/gic.c	Mon Dec 22 22:22:10 2014	(r276093)
+++ projects/arm_intrng/sys/arm/arm/gic.c	Mon Dec 22 22:29:48 2014	(r276094)
@@ -281,6 +281,8 @@ arm_gic_attach(device_t dev)
 	}
 
 	arm_register_pic(dev, PIC_FEATURE_IPI);
+	for (int i = 0; i < ARM_IPI_COUNT; i++)
+		arm_ipi_map_irq(dev, i, i);
 
 	/* Disable interrupt forwarding to the CPU interface */
 	gic_d_write_4(sc, GICD_CTLR, 0x00);
@@ -350,7 +352,7 @@ arm_gic_intr(void *arg)
 		return (FILTER_HANDLED);
 	}
 	
-	gic_c_write_4(sc, GICC_EOIR, active_irq);
+	//gic_c_write_4(sc, GICC_EOIR, active_irq);
 	arm_dispatch_irq(sc->gic_dev, NULL, active_irq);
 
 	return (FILTER_HANDLED);

Modified: projects/arm_intrng/sys/arm/arm/intrng.c
==============================================================================
--- projects/arm_intrng/sys/arm/arm/intrng.c	Mon Dec 22 22:22:10 2014	(r276093)
+++ projects/arm_intrng/sys/arm/arm/intrng.c	Mon Dec 22 22:29:48 2014	(r276094)
@@ -32,6 +32,8 @@
  *
  */
 
+#include "opt_platform.h"
+
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 #include <sys/param.h>
@@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/syslog.h> 
 #include <sys/malloc.h>
 #include <sys/proc.h>
+#include <sys/queue.h>
 #include <sys/bus.h>
 #include <sys/interrupt.h>
 #include <sys/conf.h>
@@ -56,9 +59,8 @@ __FBSDID("$FreeBSD$");
 
 #define	INTRNAME_LEN	(MAXCOMLEN + 1)
 
-#define	IRQ_PIC_IDX(_irq)	(((_irq) >> 8) & 0xff)
-#define	IRQ_VECTOR_IDX(_irq)	((_irq) & 0xff)
-#define	IRQ_GEN(_pic, _irq)	(((_pic) << 8) | ((_irq) & 0xff))
+
+#define MAXINTRS 1024 // XXX Need this passed in to pic registration
 
 //#define DEBUG
 #ifdef DEBUG
@@ -73,23 +75,30 @@ typedef void (*mask_fn)(void *);
 struct arm_intr_controller {
 	device_t		ic_dev;
 	phandle_t		ic_node;
-	int			ic_maxintrs;
-	struct arm_intr_handler	*ic_intrs;
+	u_int			ic_idx;
+	u_int			ic_maxintrs;
+	struct arm_intr_handler	**ic_ih_by_hwirq;
+	u_int			ic_ih_count;
+	SLIST_HEAD(, arm_intr_handler)
+				ic_ih_list;
 };
 
 struct arm_intr_handler {
-	device_t		ih_dev;
-	const char *		ih_ipi_name;
-	int			ih_intrcnt_idx;
-	int			ih_irq;
-	pcell_t			ih_cells[8];
-	int			ih_ncells;
+	SLIST_ENTRY(arm_intr_handler) ih_next_entry;
+	u_int			ih_intrcnt_idx;
+	u_int			ih_resirq;
+	u_int			ih_hwirq;
+	u_int			ih_ncells;
 	enum intr_trigger	ih_trig;
 	enum intr_polarity	ih_pol;
 	struct intr_event *	ih_event;
-	struct arm_intr_controller *ih_pic;
+	struct arm_intr_controller *ih_ic;
+	pcell_t			ih_cells[];
 };
 
+static u_int resirq_encode(u_int picidx, u_int irqidx);
+
+
 static void arm_mask_irq(void *);
 static void arm_unmask_irq(void *);
 static void arm_eoi(void *);
@@ -97,12 +106,24 @@ static void arm_eoi(void *);
 static struct arm_intr_controller arm_pics[NPIC];
 static struct arm_intr_controller *arm_ipi_pic;
 
-static int intrcnt_index = 0;
-static int last_printed = 0;
+static int intrcnt_index;
+static int intrcnt_last_printed;
 
 MALLOC_DECLARE(M_INTRNG);
 MALLOC_DEFINE(M_INTRNG, "intrng", "ARM interrupt handling");
 
+static const char *ipi_names[] = {
+	"IPI:AST",
+	"IPI:PREEMPT",
+	"IPI:RENDEZVOUS",
+	"IPI:STOP",
+	"IPI:HARDCLOCK",
+	"IPI:TLB"
+};
+CTASSERT(ARM_IPI_COUNT == nitems(ipi_names));
+
+static struct arm_intr_handler * ipi_handlers[ARM_IPI_COUNT];
+
 /* Data for statistics reporting. */
 u_long intrcnt[NIRQ];
 char intrnames[NIRQ * INTRNAME_LEN];
@@ -111,6 +132,161 @@ size_t sintrnames = sizeof(intrnames);
 int (*arm_config_irq)(int irq, enum intr_trigger trig,
     enum intr_polarity pol) = NULL;
 
+static inline struct arm_intr_controller *
+ic_from_dev(device_t dev)
+{
+	struct arm_intr_controller *ic;
+	u_int i;
+
+	for (i = 0, ic = arm_pics; i < nitems(arm_pics); i++, ic++) {
+		if (dev == ic->ic_dev)
+			return (ic);
+	}
+	return (NULL);
+}
+
+static inline struct arm_intr_controller *
+ic_from_node(phandle_t node)
+{
+	struct arm_intr_controller *ic;
+	u_int i;
+
+	for (i = 0, ic = arm_pics; i < nitems(arm_pics); i++, ic++) {
+		if (node == ic->ic_node)
+			return (ic);
+	}
+	return (NULL);
+}
+
+static struct arm_intr_controller *
+ic_create(phandle_t node)
+{
+	struct arm_intr_controller *ic;
+	u_int i;
+
+	for (i = 0, ic = arm_pics; i < nitems(arm_pics); i++, ic++) {
+		if (ic->ic_node == 0)
+			break;
+	}
+	if (i == nitems(arm_pics))
+		panic("no room to add interrupt controller");
+
+	bzero(ic, sizeof(ic));
+	ic->ic_idx = i;
+	ic->ic_node = node;
+	SLIST_INIT(&ic->ic_ih_list);
+
+	debugf("allocated new interrupt controller at index %d ptr %p for node %d\n", i, ic, node);
+	return (ic);
+}
+
+static void
+ic_setup_dev(struct arm_intr_controller *ic, device_t dev, u_int maxintrs)
+{
+	struct arm_intr_handler *ih;
+
+	ic->ic_dev = dev;
+	ic->ic_maxintrs = maxintrs;
+	ic->ic_ih_by_hwirq = malloc(maxintrs * sizeof(struct arm_intr_handler *),
+	    M_INTRNG, M_WAITOK | M_ZERO);
+	SLIST_FOREACH(ih, &ic->ic_ih_list, ih_next_entry) {
+		PIC_TRANSLATE(ic->ic_dev, ih->ih_cells, &ih->ih_hwirq,
+		    &ih->ih_trig, &ih->ih_pol);
+		ic->ic_ih_by_hwirq[ih->ih_hwirq] = ih;
+	}
+}
+
+static struct arm_intr_handler *
+ic_add_ih(struct arm_intr_controller *ic, pcell_t *cells, u_int ncells)
+{
+	struct arm_intr_handler *ih;
+	u_int cellsize;
+
+	cellsize = ncells * sizeof(*cells);
+	ih = malloc(sizeof(*ih) + cellsize, M_INTRNG, M_WAITOK | M_ZERO);
+	memcpy(ih->ih_cells, cells, cellsize);
+	ih->ih_ncells = ncells;
+	ih->ih_ic = ic;
+	ih->ih_resirq = resirq_encode(ic->ic_idx, ic->ic_ih_count++);
+	SLIST_INSERT_HEAD(&ic->ic_ih_list, ih, ih_next_entry);
+	return (ih);
+}
+
+static void
+ic_index_ih_by_hwirq(struct arm_intr_controller *ic, 
+    struct arm_intr_handler *ih)
+{
+
+	KASSERT(ih->ih_hwirq < ic->ic_maxintrs, ("%s irq %u too large", 
+	    device_get_nameunit(ic->ic_dev), ih->ih_hwirq));
+	KASSERT(ic->ic_ih_by_hwirq[ih->ih_hwirq] == NULL, 
+	    ("%s irq %u already registered", device_get_nameunit(ic->ic_dev),
+	    ih->ih_hwirq));
+	ic->ic_ih_by_hwirq[ih->ih_hwirq] = ih;
+}
+
+static struct arm_intr_handler *
+ih_from_fdtcells(struct arm_intr_controller *ic, pcell_t *cells,  u_int ncells)
+{
+	struct arm_intr_handler *ih;
+
+	SLIST_FOREACH(ih, &ic->ic_ih_list, ih_next_entry) {
+		if (ncells == ih->ih_ncells && memcmp(cells, ih->ih_cells, 
+		    ncells * sizeof(*cells)) == 0)
+			return (ih);
+	}
+	return (NULL);
+}
+
+static struct arm_intr_handler *
+ih_from_resirq(struct arm_intr_controller *ic, u_int resirq)
+{
+	struct arm_intr_handler *ih;
+
+	SLIST_FOREACH(ih, &ic->ic_ih_list, ih_next_entry) {
+		if (resirq == ih->ih_resirq)
+			return (ih);
+	}
+	return (NULL);
+}
+
+static struct arm_intr_handler *
+ih_from_hwirq(struct arm_intr_controller *ic, u_int hwirq)
+{
+
+	return (ic->ic_ih_by_hwirq[hwirq]);
+}
+
+static u_int
+resirq_encode(u_int picidx, u_int irqidx)
+{
+
+	return((picidx << 16) | (irqidx & 0xffff));
+}
+
+static u_int
+resirq_decode(int resirq, struct arm_intr_controller **pic, 
+   struct arm_intr_handler **pih)
+{
+	struct arm_intr_controller *ic;
+	u_int irqidx, picidx;
+
+	picidx = resirq >> 16;
+	KASSERT(picidx < nitems(arm_pics), ("bad pic index %u", picidx));
+	ic = &arm_pics[picidx];
+
+	irqidx = resirq & 0xffff;
+	KASSERT(irqidx < ic->ic_ih_count, ("bad irq index %u for pic %u",
+	    irqidx, picidx));
+
+	if (pic != NULL)
+		*pic = ic;
+	if (pih != NULL && ic != NULL)
+		*pih = ih_from_resirq(ic, resirq);
+
+	return (irqidx);
+}
+
 void
 arm_intrnames_init(void)
 {
@@ -122,9 +298,8 @@ arm_dispatch_irq(device_t dev, struct tr
 {
 	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih = NULL;
-	int i;
 
-	debugf("pic %s, tf %p, irq %d\n", device_get_nameunit(dev), tf, irq);
+//	debugf("pic %s, tf %p, irq %d\n", device_get_nameunit(dev), tf, irq);
 
 	/*
 	 * If we got null trapframe argument, that probably means
@@ -134,308 +309,189 @@ arm_dispatch_irq(device_t dev, struct tr
 	if (tf == NULL)
 		tf = PCPU_GET(curthread)->td_intr_frame;
 
-	for (ic = &arm_pics[0]; ic->ic_dev != NULL; ic++) {
-		if (ic->ic_dev == dev) {
-			for (i = 0; i < ic->ic_maxintrs; i++) {
-				ih = &ic->ic_intrs[i];
-				if (irq == ih->ih_irq)
-					goto done;
-			}
-		}
-	}
-done:
-
-	if (ic->ic_dev == NULL)
-		panic("arm_dispatch_irq: unknown irq");
-
-	debugf("requested by %s\n", ih->ih_ipi_name != NULL
-	    ? ih->ih_ipi_name
-	    : device_get_nameunit(ih->ih_dev));
+	ic = ic_from_dev(dev);
+	KASSERT(ic != NULL, ("%s: interrupt controller for %s not found", 
+	    __FUNCTION__, device_get_nameunit(dev)));
+
+	ih = ih_from_hwirq(ic, irq);
+	KASSERT(ih != NULL, ("%s: interrupt handler for %s irq %d not found",
+	    __FUNCTION__, device_get_nameunit(dev), irq));
 
 	intrcnt[ih->ih_intrcnt_idx]++;
 	if (intr_event_handle(ih->ih_event, tf) != 0) {
-		/* Stray IRQ */
+		device_printf(dev, "stray irq %d; disabled", irq);
 		arm_mask_irq(ih);
 	}
 
-	debugf("done\n");
+//	debugf("done\n");
 }
 
-static struct arm_intr_handler *
-arm_lookup_intr_handler(device_t pic, int idx)
-{
-	struct arm_intr_controller *ic;
-
-	for (ic = &arm_pics[0]; ic->ic_dev != NULL; ic++) {
-		if (ic->ic_dev != NULL && ic->ic_dev == pic)
-			return (&ic->ic_intrs[idx]);
-	}
-
-	return (NULL);
-}
-
-
 int
-arm_fdt_map_irq(phandle_t ic, pcell_t *cells, int ncells)
+arm_fdt_map_irq(phandle_t icnode, pcell_t *cells, int ncells)
 {
-	struct arm_intr_controller *pic;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
-	int i, j;
-
-	ic = OF_node_from_xref(ic);
 
-	debugf("ic %08x cells <%*D>\n", ic, ncells * sizeof(pcell_t),
+	debugf("map icnode %08x cells <%*D>\n", icnode, ncells * sizeof(pcell_t),
 	    (char *)cells, ",");
 
-	for (i = 0; arm_pics[i].ic_node != 0; i++) {
-		pic = &arm_pics[i];
-		if (pic->ic_node == ic) {
-			for (j = 0; j < pic->ic_maxintrs; j++) {
-				ih = &pic->ic_intrs[j];
-
-				/* Compare pcell contents */
-				if (!memcmp(cells, ih->ih_cells, ncells))
-					return (IRQ_GEN(i, j));
-			}
-
-			/* Not found - new entry required */
-			pic->ic_maxintrs++;
-			pic->ic_intrs = realloc(pic->ic_intrs,
-			    pic->ic_maxintrs * sizeof(struct arm_intr_handler),
-			    M_INTRNG, M_WAITOK | M_ZERO);
-
-			ih = &pic->ic_intrs[pic->ic_maxintrs - 1];
-			ih->ih_pic = pic;
-			ih->ih_ncells = ncells;
-			memcpy(ih->ih_cells, cells, ncells);
-
-			if (pic->ic_dev != NULL) {
-				/* Map IRQ number */
-				PIC_TRANSLATE(pic->ic_dev, cells, &ih->ih_irq,
-				    &ih->ih_trig, &ih->ih_pol);
+	icnode = OF_node_from_xref(icnode);
 
-				debugf("translated to irq %d\n", ih->ih_irq);
-			}
+	ic = ic_from_node(icnode);
+	if (ic == NULL)
+		ic = ic_create(icnode);
 
-			return (IRQ_GEN(i, pic->ic_maxintrs - 1));
+	ih = ih_from_fdtcells(ic, cells, ncells);
+	if (ih == NULL) {
+		ih = ic_add_ih(ic, cells, ncells);
+		if (ic->ic_dev != NULL) {
+			PIC_TRANSLATE(ic->ic_dev, ih->ih_cells, &ih->ih_hwirq,
+			    &ih->ih_trig, &ih->ih_pol);
+			ic_index_ih_by_hwirq(ic, ih);
 		}
 	}
-
-	/* 
-	 * Interrupt controller is not registered yet, so
-	 * we map a stub for it. 'i' is pointing to free
-	 * first slot in arm_pics table.
-	 */
-	debugf("allocating new ic at index %d\n", i);
-
-	pic = &arm_pics[i];
-	pic->ic_node = ic;
-	pic->ic_maxintrs = 1;
-	pic->ic_intrs = malloc(sizeof(struct arm_intr_handler), M_INTRNG,
-	    M_WAITOK | M_ZERO);
-
-	ih = &pic->ic_intrs[0];
-	ih->ih_pic = pic;
-	ih->ih_ncells = ncells;
-	memcpy(ih->ih_cells, cells, ncells);
-
-	return (IRQ_GEN(i, 0));
+	return (ih->ih_resirq);
 }
 
 const char *
-arm_describe_irq(int irq)
+arm_describe_irq(int resirq)
 {
-	struct arm_intr_controller *pic;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
+	int irqidx;
 	static char buffer[INTRNAME_LEN];
-	static char name[INTRNAME_LEN];
-
-	pic = &arm_pics[IRQ_PIC_IDX(irq)];
-
-	if (pic == NULL)
-		return ("<unknown ic>");
-
-	if (IRQ_VECTOR_IDX(irq) > pic->ic_maxintrs)
-		return ("<unknown irq>");
 
-	ih = &pic->ic_intrs[IRQ_VECTOR_IDX(irq)];
+	/* XXX static buffer, can this be called after APs released? */
 
-	if (pic->ic_dev == NULL) {
+	irqidx = resirq_decode(resirq, &ic, &ih);
+	KASSERT(ic != NULL, ("%s: bad resirq 0x%08x", resirq));
+	if (ic->ic_dev == NULL) {
 		/*
 		 * Interrupt controller not attached yet. We don't know the
 		 * IC device name nor interrupt number. All we can do is to
-		 * use FDT 'name' property.
+		 * use its index (fdt names are unbounded length).
 		 */
-		OF_getprop(ih->ih_pic->ic_node, "name", name, sizeof(name));
-		snprintf(buffer, sizeof(buffer), "%s.?", name);
-		return (buffer);
+		snprintf(buffer, sizeof(buffer), "ic%d.%d", ic->ic_idx, irqidx);
+	} else {
+		KASSERT(ih != NULL, ("%s: no handler for resirq 0x%08x\n", resirq));
+		snprintf(buffer, sizeof(buffer), "%s.%d", 
+		    device_get_nameunit(ih->ih_ic->ic_dev), ih->ih_hwirq);
 	}
-
-	snprintf(buffer, sizeof(buffer), "%s.%d",
-	    device_get_nameunit(ih->ih_pic->ic_dev), ih->ih_irq);
-
 	return (buffer);
 }
 
 void
 arm_register_pic(device_t dev, int flags)
 {
-	struct arm_intr_controller *ic = NULL;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
 	phandle_t node;
-	int i;
 
 	node = ofw_bus_get_node(dev);
-
-	/* Find room for IC */
-	for (i = 0; i < NPIC; i++) {
-		if (arm_pics[i].ic_dev != NULL)
-			continue;
-
-		if (arm_pics[i].ic_node == node) {
-			ic = &arm_pics[i];
-			break;
-		}
-
-		if (arm_pics[i].ic_node == 0) {
-			ic = &arm_pics[i];
-			break;
-		}
-	}
-
+	ic = ic_from_node(node);
 	if (ic == NULL)
-		panic("not enough room to register interrupt controller");
+		ic = ic_create(node);
 
-	ic->ic_dev = dev;
-	ic->ic_node = node;
+	ic_setup_dev(ic, dev, MAXINTRS);
 
 	/*
-	 * Normally ic_intrs is allocated by arm_fdt_map_irq(), but the nexus
-	 * root isn't described by fdt data.  If the node is -1 and the ic_intrs
-	 * array hasn't yet been allocated, we're dealing with nexus, allocate a
-	 * single entry for irq 0.
+	 * The nexus root usually isn't described by fdt data.  If the node is
+	 * -1 and the number of interrupts added is zero and the device's
+	 * name is "nexus", allocate a single entry for irq 0.
 	 */
-	if (node == -1 && ic->ic_intrs == NULL) {
-	       ic->ic_intrs = malloc(sizeof(struct arm_intr_handler), M_INTRNG,
-		   M_WAITOK | M_ZERO);
-	       ic->ic_maxintrs = 1;
-	       ih = &ic->ic_intrs[0];
-	       ih->ih_pic = ic;
-	       ih->ih_ncells = 0;
-       }
+	if (node == -1 && ic->ic_ih_count == 0 &&
+	    strcmp(device_get_name(dev), "nexus") == 0) {
+		ih = ic_add_ih(ic, NULL, 0);
+		ih->ih_hwirq = 0;
+		ic_index_ih_by_hwirq(ic, ih);
+	}
 
 	debugf("device %s node %08x slot %d\n", device_get_nameunit(dev),
-	    ic->ic_node, i);
+	    ic->ic_node, ic->ic_idx);
 
 	if (flags & PIC_FEATURE_IPI) {
-		if (arm_ipi_pic != NULL)
-			panic("there's already registered interrupt "
-			    "controller for serving IPIs");
-
+		KASSERT(arm_ipi_pic == NULL, 
+		    ("controller for IPIs is already registered"));
 		arm_ipi_pic = ic;
 	}
 
-	/* Resolve IRQ numbers for interrupt handlers added earlier */
-	for (i = 0; i < ic->ic_maxintrs; i++) {
-		ih = &ic->ic_intrs[i];
-
-		/* Map IRQ number */
-		PIC_TRANSLATE(ic->ic_dev, ih->ih_cells, &ih->ih_irq,
-		    &ih->ih_trig, &ih->ih_pol);
-
-		debugf("translated to irq %d\n", ih->ih_irq);
-	}
-
-	device_printf(dev, "registered as interrupt controller\n");
+	/*
+	 * arm_describe_irq() has to print fake names earlier when the device
+	 * issn't registered yet, emit a string that has the same fake name in
+	 * it, so that earlier output links to this device.
+	 */
+	device_printf(dev, "registered as interrupt controller ic%d\n", 
+	    ic->ic_idx);
 }
 
 void
 arm_setup_irqhandler(device_t dev, driver_filter_t *filt, 
-    void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
+    void (*hand)(void*), void *arg, int resirq, int flags, void **cookiep)
 {
-	struct arm_intr_controller *pic;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
 	const char *name;
 	int error;
-	int ipi;
-
-	if (irq < 0)
-		return;
+	int irqidx;
 
-	ipi = (flags & INTR_IPI) != 0;
-	KASSERT(!ipi || arm_ipi_pic != NULL,
-	    ("No IPI pic setup when adding an IPI"));
-	pic = ipi ? arm_ipi_pic : &arm_pics[IRQ_PIC_IDX(irq)];
-	ih = arm_lookup_intr_handler(pic->ic_dev, IRQ_VECTOR_IDX(irq));
-
-	if (ipi) {
-		name = (const char *)dev;
-		debugf("setup ipi %d\n", irq);
+	if (flags & INTR_IPI) {
+		ic = arm_ipi_pic;
+		irqidx = resirq; /* resirq is the same as hwirq for IPIs */
+		KASSERT(ic != NULL, ("%s: no interrupt controller for IPIs",
+		    __FUNCTION__));
+		ih = ipi_handlers[irqidx];
+		KASSERT(ih != NULL, 
+		    ("%s: interrupt handler for %s IPI %u not found",
+		    __FUNCTION__, device_get_nameunit(ic->ic_dev),
+		    irqidx));
+		KASSERT(irqidx < ARM_IPI_COUNT, ("IPI number too big: %u",
+		    irqidx));
+		name = ipi_names[irqidx];
+		debugf("setup ipi %u (%s)\n", irqidx, name);
 	} else {
+		irqidx = resirq_decode(resirq, &ic, &ih);
 		name = device_get_nameunit(dev);
-		debugf("setup irq %d on %s\n", IRQ_VECTOR_IDX(irq),
-		    device_get_nameunit(pic->ic_dev));
+		debugf("setup irq %s.%d on %s\n",
+		    device_get_nameunit(ic->ic_dev), ih->ih_hwirq, name);
 	}
 
-	debugf("pic %p, ih %p\n", pic, ih);
-
 	if (ih->ih_event == NULL) {
-		error = intr_event_create(&ih->ih_event, (void *)ih, 0, irq,
+		error = intr_event_create(&ih->ih_event, ih, 0, resirq,
 		    (mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq,
-		    arm_eoi, NULL, "intr%d.%d:", IRQ_PIC_IDX(irq),
-		    IRQ_VECTOR_IDX(irq));
-		
-		if (error)
+		    arm_eoi, NULL, "ic%d.%d:", ic->ic_idx, ih->ih_hwirq);
+		if (error) {
+			device_printf(dev, "intr_event_create() failed "
+			    "for irq %s.%u\n", device_get_nameunit(ic->ic_dev),
+			     ih->ih_hwirq);
 			return;
-
-		ih->ih_dev = dev;
-		ih->ih_ipi_name = ipi ? name : NULL;
-		ih->ih_pic = pic;
-
-		arm_unmask_irq(ih);
-
-		last_printed += 
-		    snprintf(intrnames + last_printed,
+		}
+		intrcnt_last_printed += 1 +
+		    snprintf(intrnames + intrcnt_last_printed,
 		    INTRNAME_LEN, "%s:%d: %s",
-		    device_get_nameunit(pic->ic_dev),
-		    ih->ih_irq, name);
-		
-		last_printed++;
-		ih->ih_intrcnt_idx = intrcnt_index;
-		intrcnt_index++;
-		
+		    device_get_nameunit(ic->ic_dev), irqidx, name);
+
+		ih->ih_intrcnt_idx = intrcnt_index++;
 	}
 
+	if (!TAILQ_EMPTY(&ih->ih_event->ie_handlers))
+		arm_mask_irq(ih);
 	intr_event_add_handler(ih->ih_event, name, filt, hand, arg,
 	    intr_priority(flags), flags, cookiep);
-
-	/* Unmask IPIs immediately */
-	if (ipi)
-		arm_unmask_irq(ih);
+	arm_unmask_irq(ih);
 }
 
 int
-arm_remove_irqhandler(int irq, void *cookie)
+arm_remove_irqhandler(int resirq, void *cookie)
 {
-	struct arm_intr_controller *pic;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
 	int error;
 
-	if (irq < 0)
-		return (ENXIO);
-
-	pic = &arm_pics[IRQ_PIC_IDX(irq)];
-	ih = arm_lookup_intr_handler(pic->ic_dev, IRQ_VECTOR_IDX(irq));
-
-	if (ih->ih_event == NULL)
-		return (ENXIO);
-
+	resirq_decode(resirq, &ic, &ih);
 	arm_mask_irq(ih);
 	error = intr_event_remove_handler(cookie);
-
 	if (!TAILQ_EMPTY(&ih->ih_event->ie_handlers))
 		arm_unmask_irq(ih);
-
 	return (error);
 }
 
@@ -444,7 +500,7 @@ arm_mask_irq(void *arg)
 {
 	struct arm_intr_handler *ih = (struct arm_intr_handler *)arg;
 
-	PIC_MASK(ih->ih_pic->ic_dev, ih->ih_irq);
+	PIC_MASK(ih->ih_ic->ic_dev, ih->ih_hwirq);
 }
 
 static void
@@ -452,7 +508,7 @@ arm_unmask_irq(void *arg)
 {
 	struct arm_intr_handler *ih = (struct arm_intr_handler *)arg;
 
-	PIC_UNMASK(ih->ih_pic->ic_dev, ih->ih_irq);
+	PIC_UNMASK(ih->ih_ic->ic_dev, ih->ih_hwirq);
 }
 
 static void
@@ -460,30 +516,46 @@ arm_eoi(void *arg)
 {
 	struct arm_intr_handler *ih = (struct arm_intr_handler *)arg;
 
-	PIC_EOI(ih->ih_pic->ic_dev, ih->ih_irq);
+	PIC_EOI(ih->ih_ic->ic_dev, ih->ih_hwirq);
 }
 
 int
-arm_intrng_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol)
+arm_intrng_config_irq(int resirq, enum intr_trigger trig, enum intr_polarity pol)
 {
-	struct arm_intr_controller *pic;
+	struct arm_intr_controller *ic;
 	struct arm_intr_handler *ih;
 
-	pic = &arm_pics[IRQ_PIC_IDX(irq)];
-	ih = arm_lookup_intr_handler(pic->ic_dev, IRQ_VECTOR_IDX(irq));
+	resirq_decode(resirq, &ic, &ih);
 
-	if (ih == NULL)
-		return (ENXIO);
-
-	return PIC_CONFIG(pic->ic_dev, ih->ih_irq, trig, pol);
+	return PIC_CONFIG(ic->ic_dev, ih->ih_hwirq, trig, pol);
 }
 
 #ifdef SMP
+
+void
+arm_ipi_map_irq(device_t dev, u_int ipi, u_int hwirq)
+{
+	struct arm_intr_controller *ic;
+	struct arm_intr_handler *ih;
+
+	ic = ic_from_dev(dev);
+	KASSERT(ic != NULL, ("ipi controller not registered"));
+
+	ih = ih_from_hwirq(ic, hwirq);
+	KASSERT(ih == NULL, ("handler already registered for IPI %u", ipi));
+
+	ih = ic_add_ih(ic, NULL, 0);
+	ih->ih_hwirq = hwirq;
+	ic_index_ih_by_hwirq(ic, ih);
+	ipi_handlers[ipi] = ih;
+	debugf("ipi %u mapped to %s.%u\n", ipi, device_get_nameunit(dev), hwirq);
+}
+
 void
 arm_init_secondary_ic(void)
 {
 
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
+	KASSERT(arm_ipi_pic != NULL, ("%s: no IPI PIC attached", __FUNCTION__));
 	PIC_INIT_SECONDARY(arm_ipi_pic->ic_dev);
 }
 
@@ -491,23 +563,25 @@ void
 pic_ipi_send(cpuset_t cpus, u_int ipi)
 {
 
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
-	PIC_IPI_SEND(arm_ipi_pic->ic_dev, cpus, ipi);
+	KASSERT(ipi < ARM_IPI_COUNT, ("invalid IPI %u", ipi));
+	KASSERT(ipi_handlers[ipi] != NULL, ("no handler for IPI %u", ipi));
+	PIC_IPI_SEND(ipi_handlers[ipi]->ih_ic->ic_dev, cpus, ipi);
 }
 
 void
 pic_ipi_clear(int ipi)
 {
-	
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
-	PIC_IPI_CLEAR(arm_ipi_pic->ic_dev, ipi);
+
+	KASSERT(ipi < ARM_IPI_COUNT, ("invalid IPI %u", ipi));
+	KASSERT(ipi_handlers[ipi] != NULL, ("no handler for IPI %u", ipi));
+	PIC_IPI_CLEAR(ipi_handlers[ipi]->ih_ic->ic_dev, ipi);
 }
 
 int
 pic_ipi_read(int ipi)
 {
 
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
+	KASSERT(arm_ipi_pic != NULL, ("no IPI interrupt controller"));
 	return (PIC_IPI_READ(arm_ipi_pic->ic_dev, ipi));
 }
 
@@ -515,16 +589,18 @@ void
 arm_unmask_ipi(int ipi)
 {
 
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
-	PIC_UNMASK(arm_ipi_pic->ic_dev, ipi);
+	KASSERT(ipi < ARM_IPI_COUNT, ("invalid IPI %u", ipi));
+	KASSERT(ipi_handlers[ipi] != NULL, ("no handler for IPI %u", ipi));
+	PIC_UNMASK(ipi_handlers[ipi]->ih_ic->ic_dev, ipi);
 }
 
 void
 arm_mask_ipi(int ipi)
 {
 
-	KASSERT(arm_ipi_pic != NULL, ("no IPI PIC attached"));
-	PIC_MASK(arm_ipi_pic->ic_dev, ipi);
+	KASSERT(ipi < ARM_IPI_COUNT, ("invalid IPI %u", ipi));
+	KASSERT(ipi_handlers[ipi] != NULL, ("no handler for IPI %u", ipi));
+	PIC_MASK(ipi_handlers[ipi]->ih_ic->ic_dev, ipi);
 }
 #endif
 

Modified: projects/arm_intrng/sys/arm/arm/mp_machdep.c
==============================================================================
--- projects/arm_intrng/sys/arm/arm/mp_machdep.c	Mon Dec 22 22:22:10 2014	(r276093)
+++ projects/arm_intrng/sys/arm/arm/mp_machdep.c	Mon Dec 22 22:29:48 2014	(r276094)
@@ -235,7 +235,7 @@ init_secondary(int cpu)
 #endif
 #endif
 				
-	for (int i = start; i <= end; i++)
+	for (int i = 0; i < ARM_IPI_COUNT; i++)
 		arm_unmask_ipi(i);
 	enable_interrupts(PSR_I);
 
@@ -352,7 +352,7 @@ release_aps(void *dummy __unused)
 #endif
 #endif
 
-	for (int i = start; i <= end; i++) {
+	for (int i = 0; i < ARM_IPI_COUNT; i++) {
 		/*
 		 * IPI handler
 		 */
@@ -361,9 +361,8 @@ release_aps(void *dummy __unused)
 		 * if we used 0, the intr code will give the trap frame
 		 * pointer instead.
 		 */
-		arm_setup_irqhandler((device_t)"ipi", ipi_handler, NULL, (void *)i, i,
+		arm_setup_irqhandler(NULL, ipi_handler, NULL, (void *)i, i,
 		    INTR_TYPE_MISC | INTR_EXCL | INTR_IPI, NULL);
-	
 		arm_unmask_ipi(i);
 	}
 	atomic_store_rel_int(&aps_ready, 1);

Modified: projects/arm_intrng/sys/arm/include/intr.h
==============================================================================
--- projects/arm_intrng/sys/arm/include/intr.h	Mon Dec 22 22:22:10 2014	(r276093)
+++ projects/arm_intrng/sys/arm/include/intr.h	Mon Dec 22 22:29:48 2014	(r276094)
@@ -67,6 +67,7 @@ int arm_intrng_config_irq(int, enum intr
 
 #ifdef SMP
 void arm_init_secondary_ic(void);
+void arm_ipi_map_irq(device_t, u_int, u_int);
 void arm_unmask_ipi(int);
 void arm_mask_ipi(int);
 #endif

Modified: projects/arm_intrng/sys/arm/include/smp.h
==============================================================================
--- projects/arm_intrng/sys/arm/include/smp.h	Mon Dec 22 22:22:10 2014	(r276093)
+++ projects/arm_intrng/sys/arm/include/smp.h	Mon Dec 22 22:29:48 2014	(r276094)
@@ -6,13 +6,17 @@
 #include <sys/_cpuset.h>
 #include <machine/pcb.h>
 
-#define IPI_AST		0
-#define IPI_PREEMPT	2
-#define IPI_RENDEZVOUS	3
-#define IPI_STOP	4
-#define IPI_STOP_HARD	4
-#define IPI_HARDCLOCK	6
-#define IPI_TLB		7
+enum {
+	IPI_AST,
+	IPI_PREEMPT,
+	IPI_RENDEZVOUS,
+	IPI_STOP,
+	IPI_STOP_HARD = IPI_STOP, /* These are synonyms on arm. */
+	IPI_HARDCLOCK,
+	IPI_TLB,
+	ARM_IPI_COUNT
+};
+
 
 void	init_secondary(int cpu);
 void	mpentry(void);


More information about the svn-src-projects mailing list