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