Date: Mon, 22 Dec 2014 22:29:49 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r276094 - in projects/arm_intrng/sys/arm: arm include Message-ID: <201412222229.sBMMTnTI001205@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412222229.sBMMTnTI001205>