[intrng] Migrate the intrng code from sys/arm/arm to sys/kern/subr_intr.c.
The ci20 port (by kan@) is going to reuse almost all of the intrng code since the SoC in question looks suspiciously like someone took an ARM SoC design and replaced the ARM core with a MIPS core. * migrate out the code; * rename ARM_ -> INTR_; * rename arm_ -> intr_; * move the interrupt flush routine from intr.c / intrng.c into arm/machdep_intr.c - removing the code duplication and removing the ARM specific bits from here. Thanks to the Star Wars: The Force Awakens premiere line for allowing me a couple hours of quiet time to finish the universe builds. Tested: * make universe TODO: * The structure definitions in subr_intr.c still includes machine/intr.h which requires one duplicates all of the intrng definitions in the platform code (which kan has done, and I think we don't have to.) Instead I should break out the generic things (function declarations, common intr structures, etc) into a separate header. * Kan has requested I make the PIC based IPI stuff optional.
This commit is contained in:
parent
6a607537da
commit
2b3ad18853
@ -61,7 +61,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -87,7 +87,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -351,7 +351,7 @@ platform_mp_init_secondary(void)
|
|||||||
* each AP.
|
* each AP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -410,7 +410,7 @@ ASENTRY_NP(irq_entry)
|
|||||||
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
|
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
|
||||||
adr lr, exception_exit /* Return from handler via standard */
|
adr lr, exception_exit /* Return from handler via standard */
|
||||||
mov r0, sp /* exception exit routine. Pass the */
|
mov r0, sp /* exception exit routine. Pass the */
|
||||||
b _C_LABEL(arm_irq_handler)/* trapframe to the handler. */
|
b _C_LABEL(intr_irq_handler)/* trapframe to the handler. */
|
||||||
END(irq_entry)
|
END(irq_entry)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -120,14 +120,14 @@ __FBSDID("$FreeBSD$");
|
|||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
static u_int gic_irq_cpu;
|
static u_int gic_irq_cpu;
|
||||||
static int arm_gic_intr(void *);
|
static int arm_gic_intr(void *);
|
||||||
static int arm_gic_bind(device_t dev, struct arm_irqsrc *isrc);
|
static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct arm_gic_softc {
|
struct arm_gic_softc {
|
||||||
device_t gic_dev;
|
device_t gic_dev;
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
void * gic_intrhand;
|
void * gic_intrhand;
|
||||||
struct arm_irqsrc ** gic_irqs;
|
struct intr_irqsrc ** gic_irqs;
|
||||||
#endif
|
#endif
|
||||||
struct resource * gic_res[3];
|
struct resource * gic_res[3];
|
||||||
bus_space_tag_t gic_c_bst;
|
bus_space_tag_t gic_c_bst;
|
||||||
@ -216,7 +216,7 @@ static void
|
|||||||
arm_gic_init_secondary(device_t dev)
|
arm_gic_init_secondary(device_t dev)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
u_int irq;
|
u_int irq;
|
||||||
|
|
||||||
for (irq = 0; irq < sc->nirqs; irq += 4)
|
for (irq = 0; irq < sc->nirqs; irq += 4)
|
||||||
@ -250,7 +250,7 @@ arm_gic_init_secondary(device_t dev)
|
|||||||
isrc = sc->gic_irqs[irq];
|
isrc = sc->gic_irqs[irq];
|
||||||
if (isrc == NULL || isrc->isrc_handlers == 0)
|
if (isrc == NULL || isrc->isrc_handlers == 0)
|
||||||
continue;
|
continue;
|
||||||
if (isrc->isrc_flags & ARM_ISRCF_BOUND) {
|
if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
|
||||||
if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
|
if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
|
||||||
gic_irq_unmask(sc, irq);
|
gic_irq_unmask(sc, irq);
|
||||||
} else {
|
} else {
|
||||||
@ -456,7 +456,7 @@ arm_gic_attach(device_t dev)
|
|||||||
* Now, when everything is initialized, it's right time to
|
* Now, when everything is initialized, it's right time to
|
||||||
* register interrupt controller to interrupt framefork.
|
* register interrupt controller to interrupt framefork.
|
||||||
*/
|
*/
|
||||||
if (arm_pic_register(dev, xref) != 0) {
|
if (intr_pic_register(dev, xref) != 0) {
|
||||||
device_printf(dev, "could not register PIC\n");
|
device_printf(dev, "could not register PIC\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -468,23 +468,23 @@ arm_gic_attach(device_t dev)
|
|||||||
*/
|
*/
|
||||||
pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
|
pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
|
||||||
if (pxref == 0 || xref == pxref) {
|
if (pxref == 0 || xref == pxref) {
|
||||||
if (arm_pic_claim_root(dev, xref, arm_gic_intr, sc,
|
if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
|
||||||
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
|
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
|
||||||
device_printf(dev, "could not set PIC as a root\n");
|
device_printf(dev, "could not set PIC as a root\n");
|
||||||
arm_pic_unregister(dev, xref);
|
intr_pic_unregister(dev, xref);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sc->gic_res[2] == NULL) {
|
if (sc->gic_res[2] == NULL) {
|
||||||
device_printf(dev,
|
device_printf(dev,
|
||||||
"not root PIC must have defined interrupt\n");
|
"not root PIC must have defined interrupt\n");
|
||||||
arm_pic_unregister(dev, xref);
|
intr_pic_unregister(dev, xref);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
|
if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
|
||||||
arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
|
arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
|
||||||
device_printf(dev, "could not setup irq handler\n");
|
device_printf(dev, "could not setup irq handler\n");
|
||||||
arm_pic_unregister(dev, xref);
|
intr_pic_unregister(dev, xref);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,7 +508,7 @@ static int
|
|||||||
arm_gic_intr(void *arg)
|
arm_gic_intr(void *arg)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = arg;
|
struct arm_gic_softc *sc = arg;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
uint32_t irq_active_reg, irq;
|
uint32_t irq_active_reg, irq;
|
||||||
struct trapframe *tf;
|
struct trapframe *tf;
|
||||||
|
|
||||||
@ -560,7 +560,7 @@ arm_gic_intr(void *arg)
|
|||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
/* Call EOI for all IPI before dispatch. */
|
/* Call EOI for all IPI before dispatch. */
|
||||||
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
|
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
|
||||||
arm_ipi_dispatch(isrc, tf);
|
intr_ipi_dispatch(isrc, tf);
|
||||||
goto next_irq;
|
goto next_irq;
|
||||||
#else
|
#else
|
||||||
device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
|
device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
|
||||||
@ -576,7 +576,7 @@ arm_gic_intr(void *arg)
|
|||||||
if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
|
if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
|
||||||
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
|
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
|
||||||
|
|
||||||
arm_irq_dispatch(isrc, tf);
|
intr_irq_dispatch(isrc, tf);
|
||||||
|
|
||||||
next_irq:
|
next_irq:
|
||||||
arm_irq_memory_barrier(irq);
|
arm_irq_memory_barrier(irq);
|
||||||
@ -589,7 +589,7 @@ arm_gic_intr(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gic_attach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq)
|
gic_attach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -609,16 +609,16 @@ gic_attach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq)
|
|||||||
|
|
||||||
name = device_get_nameunit(sc->gic_dev);
|
name = device_get_nameunit(sc->gic_dev);
|
||||||
if (irq <= GIC_LAST_SGI)
|
if (irq <= GIC_LAST_SGI)
|
||||||
arm_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI);
|
intr_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI);
|
||||||
else if (irq <= GIC_LAST_PPI)
|
else if (irq <= GIC_LAST_PPI)
|
||||||
arm_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI);
|
intr_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI);
|
||||||
else
|
else
|
||||||
arm_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI);
|
intr_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gic_detach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq)
|
gic_detach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
|
||||||
{
|
{
|
||||||
|
|
||||||
mtx_lock_spin(&sc->mutex);
|
mtx_lock_spin(&sc->mutex);
|
||||||
@ -630,7 +630,7 @@ gic_detach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq)
|
|||||||
isrc->isrc_data = 0;
|
isrc->isrc_data = 0;
|
||||||
mtx_unlock_spin(&sc->mutex);
|
mtx_unlock_spin(&sc->mutex);
|
||||||
|
|
||||||
arm_irq_set_name(isrc, "");
|
intr_irq_set_name(isrc, "");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,15 +696,15 @@ gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp)
|
|||||||
{
|
{
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ARM_IRQ_NSPC_PLAIN:
|
case INTR_IRQ_NSPC_PLAIN:
|
||||||
*irqp = num;
|
*irqp = num;
|
||||||
return (*irqp < sc->nirqs ? 0 : EINVAL);
|
return (*irqp < sc->nirqs ? 0 : EINVAL);
|
||||||
|
|
||||||
case ARM_IRQ_NSPC_IRQ:
|
case INTR_IRQ_NSPC_IRQ:
|
||||||
*irqp = num + GIC_FIRST_PPI;
|
*irqp = num + GIC_FIRST_PPI;
|
||||||
return (*irqp < sc->nirqs ? 0 : EINVAL);
|
return (*irqp < sc->nirqs ? 0 : EINVAL);
|
||||||
|
|
||||||
case ARM_IRQ_NSPC_IPI:
|
case INTR_IRQ_NSPC_IPI:
|
||||||
*irqp = num + GIC_FIRST_SGI;
|
*irqp = num + GIC_FIRST_SGI;
|
||||||
return (*irqp < GIC_LAST_SGI ? 0 : EINVAL);
|
return (*irqp < GIC_LAST_SGI ? 0 : EINVAL);
|
||||||
|
|
||||||
@ -714,7 +714,7 @@ gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gic_map_nspc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp)
|
gic_map_nspc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -727,7 +727,7 @@ gic_map_nspc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp)
|
|||||||
|
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
static int
|
static int
|
||||||
gic_map_fdt(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp)
|
gic_map_fdt(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
|
||||||
{
|
{
|
||||||
u_int irq, tripol;
|
u_int irq, tripol;
|
||||||
enum intr_trigger trig;
|
enum intr_trigger trig;
|
||||||
@ -773,7 +773,7 @@ gic_map_fdt(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp)
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
isrc->isrc_nspc_type = ARM_IRQ_NSPC_PLAIN;
|
isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
|
||||||
isrc->isrc_nspc_num = irq;
|
isrc->isrc_nspc_num = irq;
|
||||||
isrc->isrc_trig = trig;
|
isrc->isrc_trig = trig;
|
||||||
isrc->isrc_pol = pol;
|
isrc->isrc_pol = pol;
|
||||||
@ -784,16 +784,16 @@ gic_map_fdt(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
arm_gic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu)
|
arm_gic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
u_int irq;
|
u_int irq;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (isrc->isrc_type == ARM_ISRCT_NAMESPACE)
|
if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
|
||||||
error = gic_map_nspc(sc, isrc, &irq);
|
error = gic_map_nspc(sc, isrc, &irq);
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
else if (isrc->isrc_type == ARM_ISRCT_FDT)
|
else if (isrc->isrc_type == INTR_ISRCT_FDT)
|
||||||
error = gic_map_fdt(sc, isrc, &irq);
|
error = gic_map_fdt(sc, isrc, &irq);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
@ -805,7 +805,7 @@ arm_gic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
u_int irq = isrc->isrc_data;
|
u_int irq = isrc->isrc_data;
|
||||||
@ -820,7 +820,7 @@ arm_gic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
* pic_enable_source() and pic_disable_source() should act on
|
* pic_enable_source() and pic_disable_source() should act on
|
||||||
* per CPU basis only. Thus, it should be solved here somehow.
|
* per CPU basis only. Thus, it should be solved here somehow.
|
||||||
*/
|
*/
|
||||||
if (isrc->isrc_flags & ARM_ISRCF_PERCPU)
|
if (isrc->isrc_flags & INTR_ISRCF_PERCPU)
|
||||||
CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
|
CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
|
||||||
|
|
||||||
gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol);
|
gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol);
|
||||||
@ -828,7 +828,7 @@ arm_gic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_enable_source(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_enable_source(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
u_int irq = isrc->isrc_data;
|
u_int irq = isrc->isrc_data;
|
||||||
@ -838,7 +838,7 @@ arm_gic_enable_source(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_disable_source(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_disable_source(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
u_int irq = isrc->isrc_data;
|
u_int irq = isrc->isrc_data;
|
||||||
@ -847,7 +847,7 @@ arm_gic_disable_source(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
arm_gic_unregister(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_unregister(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
u_int irq = isrc->isrc_data;
|
u_int irq = isrc->isrc_data;
|
||||||
@ -856,7 +856,7 @@ arm_gic_unregister(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_pre_ithread(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
|
|
||||||
@ -865,7 +865,7 @@ arm_gic_pre_ithread(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_post_ithread(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_irq_memory_barrier(0);
|
arm_irq_memory_barrier(0);
|
||||||
@ -873,7 +873,7 @@ arm_gic_post_ithread(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_gic_post_filter(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
|
|
||||||
@ -886,7 +886,7 @@ arm_gic_post_filter(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
arm_gic_bind(device_t dev, struct arm_irqsrc *isrc)
|
arm_gic_bind(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
uint32_t irq = isrc->isrc_data;
|
uint32_t irq = isrc->isrc_data;
|
||||||
@ -895,7 +895,7 @@ arm_gic_bind(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
if (CPU_EMPTY(&isrc->isrc_cpu)) {
|
if (CPU_EMPTY(&isrc->isrc_cpu)) {
|
||||||
gic_irq_cpu = arm_irq_next_cpu(gic_irq_cpu, &all_cpus);
|
gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
|
||||||
CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
|
CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
|
||||||
}
|
}
|
||||||
return (gic_bind(sc, irq, &isrc->isrc_cpu));
|
return (gic_bind(sc, irq, &isrc->isrc_cpu));
|
||||||
@ -903,7 +903,7 @@ arm_gic_bind(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
static void
|
static void
|
||||||
arm_gic_ipi_send(device_t dev, struct arm_irqsrc *isrc, cpuset_t cpus)
|
arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
|
||||||
{
|
{
|
||||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||||
uint32_t irq, val = 0, i;
|
uint32_t irq, val = 0, i;
|
||||||
@ -1097,7 +1097,7 @@ arm_get_next_irq(int last_irq)
|
|||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
void
|
void
|
||||||
arm_pic_init_secondary(void)
|
intr_pic_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_gic_init_secondary(gic_sc->gic_dev);
|
arm_gic_init_secondary(gic_sc->gic_dev);
|
||||||
|
@ -70,7 +70,7 @@ typedef void (*mask_fn)(void *);
|
|||||||
|
|
||||||
static struct intr_event *intr_events[NIRQ];
|
static struct intr_event *intr_events[NIRQ];
|
||||||
|
|
||||||
void arm_irq_handler(struct trapframe *);
|
void intr_irq_handler(struct trapframe *);
|
||||||
|
|
||||||
void (*arm_post_filter)(void *) = NULL;
|
void (*arm_post_filter)(void *) = NULL;
|
||||||
int (*arm_config_irq)(int irq, enum intr_trigger trig,
|
int (*arm_config_irq)(int irq, enum intr_trigger trig,
|
||||||
@ -104,7 +104,7 @@ SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
|
|||||||
|
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
int
|
int
|
||||||
arm_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells)
|
intr_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells)
|
||||||
{
|
{
|
||||||
fdt_pic_decode_t intr_decode;
|
fdt_pic_decode_t intr_decode;
|
||||||
phandle_t intr_parent;
|
phandle_t intr_parent;
|
||||||
@ -179,7 +179,7 @@ dosoftints(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arm_irq_handler(struct trapframe *frame)
|
intr_irq_handler(struct trapframe *frame)
|
||||||
{
|
{
|
||||||
struct intr_event *event;
|
struct intr_event *event;
|
||||||
int i;
|
int i;
|
||||||
@ -199,67 +199,3 @@ arm_irq_handler(struct trapframe *frame)
|
|||||||
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, frame);
|
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, frame);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* arm_irq_memory_barrier()
|
|
||||||
*
|
|
||||||
* Ensure all writes to device memory have reached devices before proceeding.
|
|
||||||
*
|
|
||||||
* This is intended to be called from the post-filter and post-thread routines
|
|
||||||
* of an interrupt controller implementation. A peripheral device driver should
|
|
||||||
* use bus_space_barrier() if it needs to ensure a write has reached the
|
|
||||||
* hardware for some reason other than clearing interrupt conditions.
|
|
||||||
*
|
|
||||||
* The need for this function arises from the ARM weak memory ordering model.
|
|
||||||
* Writes to locations mapped with the Device attribute bypass any caches, but
|
|
||||||
* are buffered. Multiple writes to the same device will be observed by that
|
|
||||||
* device in the order issued by the cpu. Writes to different devices may
|
|
||||||
* appear at those devices in a different order than issued by the cpu. That
|
|
||||||
* is, if the cpu writes to device A then device B, the write to device B could
|
|
||||||
* complete before the write to device A.
|
|
||||||
*
|
|
||||||
* Consider a typical device interrupt handler which services the interrupt and
|
|
||||||
* writes to a device status-acknowledge register to clear the interrupt before
|
|
||||||
* returning. That write is posted to the L2 controller which "immediately"
|
|
||||||
* places it in a store buffer and automatically drains that buffer. This can
|
|
||||||
* be less immediate than you'd think... There may be no free slots in the store
|
|
||||||
* buffers, so an existing buffer has to be drained first to make room. The
|
|
||||||
* target bus may be busy with other traffic (such as DMA for various devices),
|
|
||||||
* delaying the drain of the store buffer for some indeterminate time. While
|
|
||||||
* all this delay is happening, execution proceeds on the CPU, unwinding its way
|
|
||||||
* out of the interrupt call stack to the point where the interrupt driver code
|
|
||||||
* is ready to EOI and unmask the interrupt. The interrupt controller may be
|
|
||||||
* accessed via a faster bus than the hardware whose handler just ran; the write
|
|
||||||
* to unmask and EOI the interrupt may complete quickly while the device write
|
|
||||||
* to ack and clear the interrupt source is still lingering in a store buffer
|
|
||||||
* waiting for access to a slower bus. With the interrupt unmasked at the
|
|
||||||
* interrupt controller but still active at the device, as soon as interrupts
|
|
||||||
* are enabled on the core the device re-interrupts immediately: now you've got
|
|
||||||
* a spurious interrupt on your hands.
|
|
||||||
*
|
|
||||||
* The right way to fix this problem is for every device driver to use the
|
|
||||||
* proper bus_space_barrier() calls in its interrupt handler. For ARM a single
|
|
||||||
* barrier call at the end of the handler would work. This would have to be
|
|
||||||
* done to every driver in the system, not just arm-specific drivers.
|
|
||||||
*
|
|
||||||
* Another potential fix is to map all device memory as Strongly-Ordered rather
|
|
||||||
* than Device memory, which takes the store buffers out of the picture. This
|
|
||||||
* has a pretty big impact on overall system performance, because each strongly
|
|
||||||
* ordered memory access causes all L2 store buffers to be drained.
|
|
||||||
*
|
|
||||||
* A compromise solution is to have the interrupt controller implementation call
|
|
||||||
* this function to establish a barrier between writes to the interrupt-source
|
|
||||||
* device and writes to the interrupt controller device.
|
|
||||||
*
|
|
||||||
* This takes the interrupt number as an argument, and currently doesn't use it.
|
|
||||||
* The plan is that maybe some day there is a way to flag certain interrupts as
|
|
||||||
* "memory barrier safe" and we can avoid this overhead with them.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
arm_irq_memory_barrier(uintptr_t irq)
|
|
||||||
{
|
|
||||||
|
|
||||||
dsb();
|
|
||||||
cpu_l2cache_drain_writebuf();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
123
sys/arm/arm/machdep_intr.c
Normal file
123
sys/arm/arm/machdep_intr.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2004 Olivier Houchard.
|
||||||
|
* Copyright (c) 1994-1998 Mark Brinicombe.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Mark Brinicombe
|
||||||
|
* for the NetBSD Project.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Soft interrupt and other generic interrupt functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "opt_platform.h"
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/syslog.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/interrupt.h>
|
||||||
|
#include <sys/conf.h>
|
||||||
|
#include <sys/pmc.h>
|
||||||
|
#include <sys/pmckern.h>
|
||||||
|
|
||||||
|
#include <machine/atomic.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/intr.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* arm_irq_memory_barrier()
|
||||||
|
*
|
||||||
|
* Ensure all writes to device memory have reached devices before proceeding.
|
||||||
|
*
|
||||||
|
* This is intended to be called from the post-filter and post-thread routines
|
||||||
|
* of an interrupt controller implementation. A peripheral device driver should
|
||||||
|
* use bus_space_barrier() if it needs to ensure a write has reached the
|
||||||
|
* hardware for some reason other than clearing interrupt conditions.
|
||||||
|
*
|
||||||
|
* The need for this function arises from the ARM weak memory ordering model.
|
||||||
|
* Writes to locations mapped with the Device attribute bypass any caches, but
|
||||||
|
* are buffered. Multiple writes to the same device will be observed by that
|
||||||
|
* device in the order issued by the cpu. Writes to different devices may
|
||||||
|
* appear at those devices in a different order than issued by the cpu. That
|
||||||
|
* is, if the cpu writes to device A then device B, the write to device B could
|
||||||
|
* complete before the write to device A.
|
||||||
|
*
|
||||||
|
* Consider a typical device interrupt handler which services the interrupt and
|
||||||
|
* writes to a device status-acknowledge register to clear the interrupt before
|
||||||
|
* returning. That write is posted to the L2 controller which "immediately"
|
||||||
|
* places it in a store buffer and automatically drains that buffer. This can
|
||||||
|
* be less immediate than you'd think... There may be no free slots in the store
|
||||||
|
* buffers, so an existing buffer has to be drained first to make room. The
|
||||||
|
* target bus may be busy with other traffic (such as DMA for various devices),
|
||||||
|
* delaying the drain of the store buffer for some indeterminate time. While
|
||||||
|
* all this delay is happening, execution proceeds on the CPU, unwinding its way
|
||||||
|
* out of the interrupt call stack to the point where the interrupt driver code
|
||||||
|
* is ready to EOI and unmask the interrupt. The interrupt controller may be
|
||||||
|
* accessed via a faster bus than the hardware whose handler just ran; the write
|
||||||
|
* to unmask and EOI the interrupt may complete quickly while the device write
|
||||||
|
* to ack and clear the interrupt source is still lingering in a store buffer
|
||||||
|
* waiting for access to a slower bus. With the interrupt unmasked at the
|
||||||
|
* interrupt controller but still active at the device, as soon as interrupts
|
||||||
|
* are enabled on the core the device re-interrupts immediately: now you've got
|
||||||
|
* a spurious interrupt on your hands.
|
||||||
|
*
|
||||||
|
* The right way to fix this problem is for every device driver to use the
|
||||||
|
* proper bus_space_barrier() calls in its interrupt handler. For ARM a single
|
||||||
|
* barrier call at the end of the handler would work. This would have to be
|
||||||
|
* done to every driver in the system, not just arm-specific drivers.
|
||||||
|
*
|
||||||
|
* Another potential fix is to map all device memory as Strongly-Ordered rather
|
||||||
|
* than Device memory, which takes the store buffers out of the picture. This
|
||||||
|
* has a pretty big impact on overall system performance, because each strongly
|
||||||
|
* ordered memory access causes all L2 store buffers to be drained.
|
||||||
|
*
|
||||||
|
* A compromise solution is to have the interrupt controller implementation call
|
||||||
|
* this function to establish a barrier between writes to the interrupt-source
|
||||||
|
* device and writes to the interrupt controller device.
|
||||||
|
*
|
||||||
|
* This takes the interrupt number as an argument, and currently doesn't use it.
|
||||||
|
* The plan is that maybe some day there is a way to flag certain interrupts as
|
||||||
|
* "memory barrier safe" and we can avoid this overhead with them.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
arm_irq_memory_barrier(uintptr_t irq)
|
||||||
|
{
|
||||||
|
|
||||||
|
dsb();
|
||||||
|
cpu_l2cache_drain_writebuf();
|
||||||
|
}
|
||||||
|
|
@ -443,12 +443,12 @@ release_aps(void *dummy __unused)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
arm_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0);
|
intr_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0);
|
||||||
arm_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0);
|
intr_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0);
|
||||||
arm_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0);
|
intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0);
|
||||||
arm_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0);
|
intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0);
|
||||||
arm_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0);
|
intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0);
|
||||||
arm_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0);
|
intr_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef IPI_IRQ_START
|
#ifdef IPI_IRQ_START
|
||||||
|
@ -267,7 +267,7 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
|
|||||||
int ret = ENODEV;
|
int ret = ENODEV;
|
||||||
|
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
ret = arm_irq_config(irq, trig, pol);
|
ret = intr_irq_config(irq, trig, pol);
|
||||||
#else
|
#else
|
||||||
if (arm_config_irq)
|
if (arm_config_irq)
|
||||||
ret = (*arm_config_irq)(irq, trig, pol);
|
ret = (*arm_config_irq)(irq, trig, pol);
|
||||||
@ -286,7 +286,7 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
|||||||
|
|
||||||
for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
|
for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
arm_irq_add_handler(child, filt, intr, arg, irq, flags,
|
intr_irq_add_handler(child, filt, intr, arg, irq, flags,
|
||||||
cookiep);
|
cookiep);
|
||||||
#else
|
#else
|
||||||
arm_setup_irqhandler(device_get_nameunit(child),
|
arm_setup_irqhandler(device_get_nameunit(child),
|
||||||
@ -302,7 +302,7 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
|
|||||||
{
|
{
|
||||||
|
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
return (arm_irq_remove_handler(child, rman_get_start(r), ih));
|
return (intr_irq_remove_handler(child, rman_get_start(r), ih));
|
||||||
#else
|
#else
|
||||||
return (arm_remove_irqhandler(rman_get_start(r), ih));
|
return (arm_remove_irqhandler(rman_get_start(r), ih));
|
||||||
#endif
|
#endif
|
||||||
@ -314,7 +314,7 @@ nexus_describe_intr(device_t dev, device_t child, struct resource *irq,
|
|||||||
void *cookie, const char *descr)
|
void *cookie, const char *descr)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (arm_irq_describe(rman_get_start(irq), cookie, descr));
|
return (intr_irq_describe(rman_get_start(irq), cookie, descr));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
@ -322,7 +322,7 @@ static int
|
|||||||
nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
|
nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (arm_irq_bind(rman_get_start(irq), cpu));
|
return (intr_irq_bind(rman_get_start(irq), cpu));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -396,6 +396,6 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
|
|||||||
pcell_t *intr)
|
pcell_t *intr)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (arm_fdt_map_irq(iparent, intr, icells));
|
return (intr_fdt_map_irq(iparent, intr, icells));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,7 +69,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -101,7 +101,7 @@ struct imx51_gpio_softc {
|
|||||||
bus_space_handle_t sc_ioh;
|
bus_space_handle_t sc_ioh;
|
||||||
int gpio_npins;
|
int gpio_npins;
|
||||||
struct gpio_pin gpio_pins[NGPIO];
|
struct gpio_pin gpio_pins[NGPIO];
|
||||||
struct arm_irqsrc *gpio_pic_irqsrc[NGPIO];
|
struct intr_irqsrc *gpio_pic_irqsrc[NGPIO];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ofw_compat_data compat_data[] = {
|
static struct ofw_compat_data compat_data[] = {
|
||||||
@ -149,7 +149,7 @@ static int imx51_gpio_pin_toggle(device_t, uint32_t pin);
|
|||||||
* this is teardown_intr
|
* this is teardown_intr
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gpio_pic_disable_intr(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
u_int irq;
|
u_int irq;
|
||||||
@ -168,7 +168,7 @@ gpio_pic_disable_intr(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
* this is mask_intr
|
* this is mask_intr
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gpio_pic_disable_source(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_disable_source(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ gpio_pic_disable_source(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
* this is setup_intr
|
* this is setup_intr
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gpio_pic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
int icfg;
|
int icfg;
|
||||||
@ -226,7 +226,7 @@ gpio_pic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
* this is unmask_intr
|
* this is unmask_intr
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gpio_pic_enable_source(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_enable_source(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ gpio_pic_enable_source(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpio_pic_post_filter(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ gpio_pic_post_filter(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpio_pic_post_ithread(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_irq_memory_barrier(0);
|
arm_irq_memory_barrier(0);
|
||||||
@ -258,7 +258,7 @@ gpio_pic_post_ithread(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpio_pic_pre_ithread(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
gpio_pic_disable_source(dev, isrc);
|
gpio_pic_disable_source(dev, isrc);
|
||||||
@ -268,7 +268,7 @@ gpio_pic_pre_ithread(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
* intrng calls this to make a new isrc known to us.
|
* intrng calls this to make a new isrc known to us.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
gpio_pic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu)
|
gpio_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
u_int irq, tripol;
|
u_int irq, tripol;
|
||||||
@ -320,7 +320,7 @@ gpio_pic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu)
|
|||||||
tripol);
|
tripol);
|
||||||
return (ENOTSUP);
|
return (ENOTSUP);
|
||||||
}
|
}
|
||||||
isrc->isrc_nspc_type = ARM_IRQ_NSPC_PLAIN;
|
isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
|
||||||
isrc->isrc_nspc_num = irq;
|
isrc->isrc_nspc_num = irq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -337,12 +337,12 @@ gpio_pic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu)
|
|||||||
isrc->isrc_data = irq;
|
isrc->isrc_data = irq;
|
||||||
mtx_unlock_spin(&sc->sc_mtx);
|
mtx_unlock_spin(&sc->sc_mtx);
|
||||||
|
|
||||||
arm_irq_set_name(isrc, "%s,%u", device_get_nameunit(sc->dev), irq);
|
intr_irq_set_name(isrc, "%s,%u", device_get_nameunit(sc->dev), irq);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gpio_pic_unregister(device_t dev, struct arm_irqsrc *isrc)
|
gpio_pic_unregister(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct imx51_gpio_softc *sc;
|
struct imx51_gpio_softc *sc;
|
||||||
u_int irq;
|
u_int irq;
|
||||||
@ -359,7 +359,7 @@ gpio_pic_unregister(device_t dev, struct arm_irqsrc *isrc)
|
|||||||
isrc->isrc_data = 0;
|
isrc->isrc_data = 0;
|
||||||
mtx_unlock_spin(&sc->sc_mtx);
|
mtx_unlock_spin(&sc->sc_mtx);
|
||||||
|
|
||||||
arm_irq_set_name(isrc, "");
|
intr_irq_set_name(isrc, "");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ gpio_pic_filter(void *arg)
|
|||||||
if ((interrupts & 0x1) == 0)
|
if ((interrupts & 0x1) == 0)
|
||||||
continue;
|
continue;
|
||||||
if (sc->gpio_pic_irqsrc[i])
|
if (sc->gpio_pic_irqsrc[i])
|
||||||
arm_irq_dispatch(sc->gpio_pic_irqsrc[i], curthread->td_intr_frame);
|
intr_irq_dispatch(sc->gpio_pic_irqsrc[i], curthread->td_intr_frame);
|
||||||
else
|
else
|
||||||
device_printf(sc->dev, "spurious interrupt %d\n", i);
|
device_printf(sc->dev, "spurious interrupt %d\n", i);
|
||||||
}
|
}
|
||||||
@ -656,7 +656,7 @@ imx51_gpio_attach(device_t dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARM_INTRNG
|
#ifdef ARM_INTRNG
|
||||||
arm_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
|
intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
|
||||||
#endif
|
#endif
|
||||||
sc->sc_busdev = gpiobus_attach_bus(dev);
|
sc->sc_busdev = gpiobus_attach_bus(dev);
|
||||||
|
|
||||||
|
@ -51,33 +51,33 @@
|
|||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
#define INTR_SOLO INTR_MD1
|
#define INTR_SOLO INTR_MD1
|
||||||
typedef int arm_irq_filter_t(void *arg, struct trapframe *tf);
|
typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
|
||||||
#else
|
#else
|
||||||
typedef int arm_irq_filter_t(void *arg);
|
typedef int intr_irq_filter_t(void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ARM_ISRC_NAMELEN (MAXCOMLEN + 1)
|
#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1)
|
||||||
|
|
||||||
typedef void arm_ipi_filter_t(void *arg);
|
typedef void intr_ipi_filter_t(void *arg);
|
||||||
|
|
||||||
enum arm_isrc_type {
|
enum intr_isrc_type {
|
||||||
ARM_ISRCT_NAMESPACE,
|
INTR_ISRCT_NAMESPACE,
|
||||||
ARM_ISRCT_FDT
|
INTR_ISRCT_FDT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARM_ISRCF_REGISTERED 0x01 /* registered in a controller */
|
#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */
|
||||||
#define ARM_ISRCF_PERCPU 0x02 /* per CPU interrupt */
|
#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */
|
||||||
#define ARM_ISRCF_BOUND 0x04 /* bound to a CPU */
|
#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */
|
||||||
|
|
||||||
/* Interrupt source definition. */
|
/* Interrupt source definition. */
|
||||||
struct arm_irqsrc {
|
struct intr_irqsrc {
|
||||||
device_t isrc_dev; /* where isrc is mapped */
|
device_t isrc_dev; /* where isrc is mapped */
|
||||||
intptr_t isrc_xref; /* device reference key */
|
intptr_t isrc_xref; /* device reference key */
|
||||||
uintptr_t isrc_data; /* device data for isrc */
|
uintptr_t isrc_data; /* device data for isrc */
|
||||||
u_int isrc_irq; /* unique identificator */
|
u_int isrc_irq; /* unique identificator */
|
||||||
enum arm_isrc_type isrc_type; /* how is isrc decribed */
|
enum intr_isrc_type isrc_type; /* how is isrc decribed */
|
||||||
u_int isrc_flags;
|
u_int isrc_flags;
|
||||||
char isrc_name[ARM_ISRC_NAMELEN];
|
char isrc_name[INTR_ISRC_NAMELEN];
|
||||||
uint16_t isrc_nspc_type;
|
uint16_t isrc_nspc_type;
|
||||||
uint16_t isrc_nspc_num;
|
uint16_t isrc_nspc_num;
|
||||||
enum intr_trigger isrc_trig;
|
enum intr_trigger isrc_trig;
|
||||||
@ -87,8 +87,8 @@ struct arm_irqsrc {
|
|||||||
u_long * isrc_count;
|
u_long * isrc_count;
|
||||||
u_int isrc_handlers;
|
u_int isrc_handlers;
|
||||||
struct intr_event * isrc_event;
|
struct intr_event * isrc_event;
|
||||||
arm_irq_filter_t * isrc_filter;
|
intr_irq_filter_t * isrc_filter;
|
||||||
arm_ipi_filter_t * isrc_ipifilter;
|
intr_ipi_filter_t * isrc_ipifilter;
|
||||||
void * isrc_arg;
|
void * isrc_arg;
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
u_int isrc_ncells;
|
u_int isrc_ncells;
|
||||||
@ -96,45 +96,45 @@ struct arm_irqsrc {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void arm_irq_set_name(struct arm_irqsrc *isrc, const char *fmt, ...)
|
void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
|
||||||
__printflike(2, 3);
|
__printflike(2, 3);
|
||||||
|
|
||||||
void arm_irq_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf);
|
void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
|
||||||
|
|
||||||
#define ARM_IRQ_NSPC_NONE 0
|
#define INTR_IRQ_NSPC_NONE 0
|
||||||
#define ARM_IRQ_NSPC_PLAIN 1
|
#define INTR_IRQ_NSPC_PLAIN 1
|
||||||
#define ARM_IRQ_NSPC_IRQ 2
|
#define INTR_IRQ_NSPC_IRQ 2
|
||||||
#define ARM_IRQ_NSPC_IPI 3
|
#define INTR_IRQ_NSPC_IPI 3
|
||||||
|
|
||||||
u_int arm_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
|
u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
u_int arm_fdt_map_irq(phandle_t, pcell_t *, u_int);
|
u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int arm_pic_register(device_t dev, intptr_t xref);
|
int intr_pic_register(device_t dev, intptr_t xref);
|
||||||
int arm_pic_unregister(device_t dev, intptr_t xref);
|
int intr_pic_unregister(device_t dev, intptr_t xref);
|
||||||
int arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter,
|
int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
|
||||||
void *arg, u_int ipicount);
|
void *arg, u_int ipicount);
|
||||||
|
|
||||||
int arm_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
|
int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
|
||||||
u_int, int, void **);
|
u_int, int, void **);
|
||||||
int arm_irq_remove_handler(device_t dev, u_int, void *);
|
int intr_irq_remove_handler(device_t dev, u_int, void *);
|
||||||
int arm_irq_config(u_int, enum intr_trigger, enum intr_polarity);
|
int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
|
||||||
int arm_irq_describe(u_int, void *, const char *);
|
int intr_irq_describe(u_int, void *, const char *);
|
||||||
|
|
||||||
u_int arm_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
|
u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
|
||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
int arm_irq_bind(u_int, int);
|
int intr_irq_bind(u_int, int);
|
||||||
|
|
||||||
void arm_ipi_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf);
|
void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
|
||||||
|
|
||||||
#define AISHF_NOALLOC 0x0001
|
#define AISHF_NOALLOC 0x0001
|
||||||
|
|
||||||
int arm_ipi_set_handler(u_int ipi, const char *name, arm_ipi_filter_t *filter,
|
int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
|
||||||
void *arg, u_int flags);
|
void *arg, u_int flags);
|
||||||
|
|
||||||
void arm_pic_init_secondary(void);
|
void intr_pic_init_secondary(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* ARM_INTRNG */
|
#else /* ARM_INTRNG */
|
||||||
@ -178,11 +178,11 @@ extern void (*arm_post_filter)(void *);
|
|||||||
extern int (*arm_config_irq)(int irq, enum intr_trigger trig,
|
extern int (*arm_config_irq)(int irq, enum intr_trigger trig,
|
||||||
enum intr_polarity pol);
|
enum intr_polarity pol);
|
||||||
|
|
||||||
void arm_pic_init_secondary(void);
|
void intr_pic_init_secondary(void);
|
||||||
|
|
||||||
#ifdef FDT
|
#ifdef FDT
|
||||||
int gic_decode_fdt(phandle_t, pcell_t *, int *, int *, int *);
|
int gic_decode_fdt(phandle_t, pcell_t *, int *, int *, int *);
|
||||||
int arm_fdt_map_irq(phandle_t, pcell_t *, int);
|
int intr_fdt_map_irq(phandle_t, pcell_t *, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ARM_INTRNG */
|
#endif /* ARM_INTRNG */
|
||||||
|
@ -16,7 +16,7 @@ enum {
|
|||||||
IPI_HARDCLOCK,
|
IPI_HARDCLOCK,
|
||||||
IPI_TLB,
|
IPI_TLB,
|
||||||
IPI_CACHE,
|
IPI_CACHE,
|
||||||
ARM_IPI_COUNT
|
INTR_IPI_COUNT
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#define IPI_AST 0
|
#define IPI_AST 0
|
||||||
|
@ -102,7 +102,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -82,7 +82,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -73,7 +73,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
void
|
void
|
||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -49,7 +49,7 @@ void
|
|||||||
platform_mp_init_secondary(void)
|
platform_mp_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
arm_pic_init_secondary();
|
intr_pic_init_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -46,16 +46,17 @@ arm/arm/identcpu.c standard
|
|||||||
arm/arm/in_cksum.c optional inet | inet6
|
arm/arm/in_cksum.c optional inet | inet6
|
||||||
arm/arm/in_cksum_arm.S optional inet | inet6
|
arm/arm/in_cksum_arm.S optional inet | inet6
|
||||||
arm/arm/intr.c optional !arm_intrng
|
arm/arm/intr.c optional !arm_intrng
|
||||||
arm/arm/intrng.c optional arm_intrng
|
kern/subr_intr.c optional arm_intrng
|
||||||
arm/arm/locore.S standard no-obj
|
arm/arm/locore.S standard no-obj
|
||||||
arm/arm/machdep.c standard
|
arm/arm/machdep.c standard
|
||||||
|
arm/arm/machdep_intr.c standard
|
||||||
arm/arm/mem.c optional mem
|
arm/arm/mem.c optional mem
|
||||||
arm/arm/minidump_machdep.c optional mem
|
arm/arm/minidump_machdep.c optional mem
|
||||||
arm/arm/mp_machdep.c optional smp
|
arm/arm/mp_machdep.c optional smp
|
||||||
arm/arm/mpcore_timer.c optional mpcore_timer
|
arm/arm/mpcore_timer.c optional mpcore_timer
|
||||||
arm/arm/nexus.c standard
|
arm/arm/nexus.c standard
|
||||||
arm/arm/physmem.c standard
|
arm/arm/physmem.c standard
|
||||||
arm/arm/pic_if.m optional arm_intrng
|
kern/pic_if.m optional arm_intrng
|
||||||
arm/arm/pl190.c optional pl190
|
arm/arm/pl190.c optional pl190
|
||||||
arm/arm/pl310.c optional pl310
|
arm/arm/pl310.c optional pl310
|
||||||
arm/arm/platform.c optional platform
|
arm/arm/platform.c optional platform
|
||||||
|
@ -36,17 +36,17 @@
|
|||||||
INTERFACE pic;
|
INTERFACE pic;
|
||||||
|
|
||||||
CODE {
|
CODE {
|
||||||
static int null_pic_bind(device_t dev, struct arm_irqsrc *isrc)
|
static int null_pic_bind(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void null_pic_disable_intr(device_t dev, struct arm_irqsrc *isrc)
|
static void null_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void null_pic_enable_intr(device_t dev, struct arm_irqsrc *isrc)
|
static void null_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -64,53 +64,53 @@ CODE {
|
|||||||
|
|
||||||
METHOD int register {
|
METHOD int register {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
boolean_t *is_percpu;
|
boolean_t *is_percpu;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD int unregister {
|
METHOD int unregister {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD void disable_intr {
|
METHOD void disable_intr {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
} DEFAULT null_pic_disable_intr;
|
} DEFAULT null_pic_disable_intr;
|
||||||
|
|
||||||
METHOD void disable_source {
|
METHOD void disable_source {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD void enable_source {
|
METHOD void enable_source {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD void enable_intr {
|
METHOD void enable_intr {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
} DEFAULT null_pic_enable_intr;
|
} DEFAULT null_pic_enable_intr;
|
||||||
|
|
||||||
METHOD void pre_ithread {
|
METHOD void pre_ithread {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD void post_ithread {
|
METHOD void post_ithread {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD void post_filter {
|
METHOD void post_filter {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD int bind {
|
METHOD int bind {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
} DEFAULT null_pic_bind;
|
} DEFAULT null_pic_bind;
|
||||||
|
|
||||||
METHOD void init_secondary {
|
METHOD void init_secondary {
|
||||||
@ -119,6 +119,6 @@ METHOD void init_secondary {
|
|||||||
|
|
||||||
METHOD void ipi_send {
|
METHOD void ipi_send {
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
cpuset_t cpus;
|
cpuset_t cpus;
|
||||||
} DEFAULT null_pic_ipi_send;
|
} DEFAULT null_pic_ipi_send;
|
@ -32,7 +32,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARM Interrupt Framework
|
* New-style Interrupt Framework
|
||||||
*
|
*
|
||||||
* TODO: - to support IPI (PPI) enabling on other CPUs if already started
|
* TODO: - to support IPI (PPI) enabling on other CPUs if already started
|
||||||
* - to complete things for removable PICs
|
* - to complete things for removable PICs
|
||||||
@ -82,33 +82,33 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
MALLOC_DECLARE(M_INTRNG);
|
MALLOC_DECLARE(M_INTRNG);
|
||||||
MALLOC_DEFINE(M_INTRNG, "intrng", "ARM interrupt handling");
|
MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
|
||||||
|
|
||||||
/* Main ARM interrupt handler called from assembler -> 'hidden' for C code. */
|
/* Main interrupt handler called from assembler -> 'hidden' for C code. */
|
||||||
void arm_irq_handler(struct trapframe *tf);
|
void intr_irq_handler(struct trapframe *tf);
|
||||||
|
|
||||||
/* Root interrupt controller stuff. */
|
/* Root interrupt controller stuff. */
|
||||||
static struct arm_irqsrc *irq_root_isrc;
|
static struct intr_irqsrc *irq_root_isrc;
|
||||||
static device_t irq_root_dev;
|
static device_t irq_root_dev;
|
||||||
static arm_irq_filter_t *irq_root_filter;
|
static intr_irq_filter_t *irq_root_filter;
|
||||||
static void *irq_root_arg;
|
static void *irq_root_arg;
|
||||||
static u_int irq_root_ipicount;
|
static u_int irq_root_ipicount;
|
||||||
|
|
||||||
/* Interrupt controller definition. */
|
/* Interrupt controller definition. */
|
||||||
struct arm_pic {
|
struct intr_pic {
|
||||||
SLIST_ENTRY(arm_pic) pic_next;
|
SLIST_ENTRY(intr_pic) pic_next;
|
||||||
intptr_t pic_xref; /* hardware identification */
|
intptr_t pic_xref; /* hardware identification */
|
||||||
device_t pic_dev;
|
device_t pic_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mtx pic_list_lock;
|
static struct mtx pic_list_lock;
|
||||||
static SLIST_HEAD(, arm_pic) pic_list;
|
static SLIST_HEAD(, intr_pic) pic_list;
|
||||||
|
|
||||||
static struct arm_pic *pic_lookup(device_t dev, intptr_t xref);
|
static struct intr_pic *pic_lookup(device_t dev, intptr_t xref);
|
||||||
|
|
||||||
/* Interrupt source definition. */
|
/* Interrupt source definition. */
|
||||||
static struct mtx isrc_table_lock;
|
static struct mtx isrc_table_lock;
|
||||||
static struct arm_irqsrc *irq_sources[NIRQ];
|
static struct intr_irqsrc *irq_sources[NIRQ];
|
||||||
u_int irq_next_free;
|
u_int irq_next_free;
|
||||||
|
|
||||||
#define IRQ_INVALID nitems(irq_sources)
|
#define IRQ_INVALID nitems(irq_sources)
|
||||||
@ -116,7 +116,7 @@ u_int irq_next_free;
|
|||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
static boolean_t irq_assign_cpu = FALSE;
|
static boolean_t irq_assign_cpu = FALSE;
|
||||||
|
|
||||||
static struct arm_irqsrc ipi_sources[ARM_IPI_COUNT];
|
static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT];
|
||||||
static u_int ipi_next_num;
|
static u_int ipi_next_num;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ static u_int ipi_next_num;
|
|||||||
* - MAXCPU counters for each IPI counters for SMP.
|
* - MAXCPU counters for each IPI counters for SMP.
|
||||||
*/
|
*/
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
#define INTRCNT_COUNT (NIRQ * 2 + ARM_IPI_COUNT * MAXCPU)
|
#define INTRCNT_COUNT (NIRQ * 2 + INTR_IPI_COUNT * MAXCPU)
|
||||||
#else
|
#else
|
||||||
#define INTRCNT_COUNT (NIRQ * 2)
|
#define INTRCNT_COUNT (NIRQ * 2)
|
||||||
#endif
|
#endif
|
||||||
@ -141,14 +141,14 @@ static u_int intrcnt_index;
|
|||||||
* Interrupt framework initialization routine.
|
* Interrupt framework initialization routine.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
arm_irq_init(void *dummy __unused)
|
intr_irq_init(void *dummy __unused)
|
||||||
{
|
{
|
||||||
|
|
||||||
SLIST_INIT(&pic_list);
|
SLIST_INIT(&pic_list);
|
||||||
mtx_init(&pic_list_lock, "arm pic list", NULL, MTX_DEF);
|
mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
|
||||||
mtx_init(&isrc_table_lock, "arm isrc table", NULL, MTX_DEF);
|
mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF);
|
||||||
}
|
}
|
||||||
SYSINIT(arm_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, arm_irq_init, NULL);
|
SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
intrcnt_setname(const char *name, int index)
|
intrcnt_setname(const char *name, int index)
|
||||||
@ -162,7 +162,7 @@ intrcnt_setname(const char *name, int index)
|
|||||||
* Update name for interrupt source with interrupt event.
|
* Update name for interrupt source with interrupt event.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
intrcnt_updatename(struct arm_irqsrc *isrc)
|
intrcnt_updatename(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* QQQ: What about stray counter name? */
|
/* QQQ: What about stray counter name? */
|
||||||
@ -174,7 +174,7 @@ intrcnt_updatename(struct arm_irqsrc *isrc)
|
|||||||
* Virtualization for interrupt source interrupt counter increment.
|
* Virtualization for interrupt source interrupt counter increment.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
isrc_increment_count(struct arm_irqsrc *isrc)
|
isrc_increment_count(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -189,7 +189,7 @@ isrc_increment_count(struct arm_irqsrc *isrc)
|
|||||||
* Virtualization for interrupt source interrupt stray counter increment.
|
* Virtualization for interrupt source interrupt stray counter increment.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
isrc_increment_straycount(struct arm_irqsrc *isrc)
|
isrc_increment_straycount(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
isrc->isrc_count[1]++;
|
isrc->isrc_count[1]++;
|
||||||
@ -199,7 +199,7 @@ isrc_increment_straycount(struct arm_irqsrc *isrc)
|
|||||||
* Virtualization for interrupt source interrupt name update.
|
* Virtualization for interrupt source interrupt name update.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isrc_update_name(struct arm_irqsrc *isrc, const char *name)
|
isrc_update_name(struct intr_irqsrc *isrc, const char *name)
|
||||||
{
|
{
|
||||||
char str[INTRNAME_LEN];
|
char str[INTRNAME_LEN];
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ isrc_update_name(struct arm_irqsrc *isrc, const char *name)
|
|||||||
* Virtualization for interrupt source interrupt counters setup.
|
* Virtualization for interrupt source interrupt counters setup.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isrc_setup_counters(struct arm_irqsrc *isrc)
|
isrc_setup_counters(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
u_int index;
|
u_int index;
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ isrc_setup_counters(struct arm_irqsrc *isrc)
|
|||||||
* Virtualization for interrupt source IPI counter increment.
|
* Virtualization for interrupt source IPI counter increment.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
isrc_increment_ipi_count(struct arm_irqsrc *isrc, u_int cpu)
|
isrc_increment_ipi_count(struct intr_irqsrc *isrc, u_int cpu)
|
||||||
{
|
{
|
||||||
|
|
||||||
isrc->isrc_count[cpu]++;
|
isrc->isrc_count[cpu]++;
|
||||||
@ -252,7 +252,7 @@ isrc_increment_ipi_count(struct arm_irqsrc *isrc, u_int cpu)
|
|||||||
* Virtualization for interrupt source IPI counters setup.
|
* Virtualization for interrupt source IPI counters setup.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isrc_setup_ipi_counters(struct arm_irqsrc *isrc, const char *name)
|
isrc_setup_ipi_counters(struct intr_irqsrc *isrc, const char *name)
|
||||||
{
|
{
|
||||||
u_int index, i;
|
u_int index, i;
|
||||||
char str[INTRNAME_LEN];
|
char str[INTRNAME_LEN];
|
||||||
@ -273,11 +273,11 @@ isrc_setup_ipi_counters(struct arm_irqsrc *isrc, const char *name)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main ARM interrupt dispatch handler. It's called straight
|
* Main interrupt dispatch handler. It's called straight
|
||||||
* from the assembler, where CPU interrupt is served.
|
* from the assembler, where CPU interrupt is served.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
arm_irq_handler(struct trapframe *tf)
|
intr_irq_handler(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
struct trapframe * oldframe;
|
struct trapframe * oldframe;
|
||||||
struct thread * td;
|
struct thread * td;
|
||||||
@ -295,12 +295,12 @@ arm_irq_handler(struct trapframe *tf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARM interrupt controller dispatch function for interrupts. It should
|
* interrupt controller dispatch function for interrupts. It should
|
||||||
* be called straight from the interrupt controller, when associated interrupt
|
* be called straight from the interrupt controller, when associated interrupt
|
||||||
* source is learned.
|
* source is learned.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
arm_irq_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf)
|
intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
|
||||||
{
|
{
|
||||||
|
|
||||||
KASSERT(isrc != NULL, ("%s: no source", __func__));
|
KASSERT(isrc != NULL, ("%s: no source", __func__));
|
||||||
@ -331,15 +331,15 @@ arm_irq_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf)
|
|||||||
/*
|
/*
|
||||||
* Allocate interrupt source.
|
* Allocate interrupt source.
|
||||||
*/
|
*/
|
||||||
static struct arm_irqsrc *
|
static struct intr_irqsrc *
|
||||||
isrc_alloc(u_int type, u_int extsize)
|
isrc_alloc(u_int type, u_int extsize)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
|
isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
|
||||||
isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
|
isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
|
||||||
isrc->isrc_type = type;
|
isrc->isrc_type = type;
|
||||||
isrc->isrc_nspc_type = ARM_IRQ_NSPC_NONE;
|
isrc->isrc_nspc_type = INTR_IRQ_NSPC_NONE;
|
||||||
isrc->isrc_trig = INTR_TRIGGER_CONFORM;
|
isrc->isrc_trig = INTR_TRIGGER_CONFORM;
|
||||||
isrc->isrc_pol = INTR_POLARITY_CONFORM;
|
isrc->isrc_pol = INTR_POLARITY_CONFORM;
|
||||||
CPU_ZERO(&isrc->isrc_cpu);
|
CPU_ZERO(&isrc->isrc_cpu);
|
||||||
@ -350,19 +350,19 @@ isrc_alloc(u_int type, u_int extsize)
|
|||||||
* Free interrupt source.
|
* Free interrupt source.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isrc_free(struct arm_irqsrc *isrc)
|
isrc_free(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
free(isrc, M_INTRNG);
|
free(isrc, M_INTRNG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arm_irq_set_name(struct arm_irqsrc *isrc, const char *fmt, ...)
|
intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(isrc->isrc_name, ARM_ISRC_NAMELEN, fmt, ap);
|
vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +377,7 @@ arm_irq_set_name(struct arm_irqsrc *isrc, const char *fmt, ...)
|
|||||||
* constantly...
|
* constantly...
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
isrc_alloc_irq_locked(struct arm_irqsrc *isrc)
|
isrc_alloc_irq_locked(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
u_int maxirqs, irq;
|
u_int maxirqs, irq;
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ isrc_alloc_irq_locked(struct arm_irqsrc *isrc)
|
|||||||
isrc->isrc_irq = irq;
|
isrc->isrc_irq = irq;
|
||||||
irq_sources[irq] = isrc;
|
irq_sources[irq] = isrc;
|
||||||
|
|
||||||
arm_irq_set_name(isrc, "irq%u", irq);
|
intr_irq_set_name(isrc, "irq%u", irq);
|
||||||
isrc_setup_counters(isrc);
|
isrc_setup_counters(isrc);
|
||||||
|
|
||||||
irq_next_free = irq + 1;
|
irq_next_free = irq + 1;
|
||||||
@ -416,7 +416,7 @@ isrc_alloc_irq_locked(struct arm_irqsrc *isrc)
|
|||||||
* Free unique interrupt number (resource handle) from interrupt source.
|
* Free unique interrupt number (resource handle) from interrupt source.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
isrc_free_irq(struct arm_irqsrc *isrc)
|
isrc_free_irq(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
u_int maxirqs;
|
u_int maxirqs;
|
||||||
|
|
||||||
@ -442,7 +442,7 @@ isrc_free_irq(struct arm_irqsrc *isrc)
|
|||||||
/*
|
/*
|
||||||
* Lookup interrupt source by interrupt number (resource handle).
|
* Lookup interrupt source by interrupt number (resource handle).
|
||||||
*/
|
*/
|
||||||
static struct arm_irqsrc *
|
static struct intr_irqsrc *
|
||||||
isrc_lookup(u_int irq)
|
isrc_lookup(u_int irq)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -454,11 +454,11 @@ isrc_lookup(u_int irq)
|
|||||||
/*
|
/*
|
||||||
* Lookup interrupt source by namespace description.
|
* Lookup interrupt source by namespace description.
|
||||||
*/
|
*/
|
||||||
static struct arm_irqsrc *
|
static struct intr_irqsrc *
|
||||||
isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
|
isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
|
||||||
{
|
{
|
||||||
u_int irq;
|
u_int irq;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
mtx_assert(&isrc_table_lock, MA_OWNED);
|
mtx_assert(&isrc_table_lock, MA_OWNED);
|
||||||
|
|
||||||
@ -477,12 +477,12 @@ isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
|
|||||||
* associated with mapped interrupt source.
|
* associated with mapped interrupt source.
|
||||||
*/
|
*/
|
||||||
u_int
|
u_int
|
||||||
arm_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
|
intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc, *new_isrc;
|
struct intr_irqsrc *isrc, *new_isrc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
new_isrc = isrc_alloc(ARM_ISRCT_NAMESPACE, 0);
|
new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0);
|
||||||
|
|
||||||
mtx_lock(&isrc_table_lock);
|
mtx_lock(&isrc_table_lock);
|
||||||
isrc = isrc_namespace_lookup(dev, type, num);
|
isrc = isrc_namespace_lookup(dev, type, num);
|
||||||
@ -511,18 +511,18 @@ arm_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
|
|||||||
/*
|
/*
|
||||||
* Lookup interrupt source by FDT description.
|
* Lookup interrupt source by FDT description.
|
||||||
*/
|
*/
|
||||||
static struct arm_irqsrc *
|
static struct intr_irqsrc *
|
||||||
isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
|
isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
|
||||||
{
|
{
|
||||||
u_int irq, cellsize;
|
u_int irq, cellsize;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
mtx_assert(&isrc_table_lock, MA_OWNED);
|
mtx_assert(&isrc_table_lock, MA_OWNED);
|
||||||
|
|
||||||
cellsize = ncells * sizeof(*cells);
|
cellsize = ncells * sizeof(*cells);
|
||||||
for (irq = 0; irq < nitems(irq_sources); irq++) {
|
for (irq = 0; irq < nitems(irq_sources); irq++) {
|
||||||
isrc = irq_sources[irq];
|
isrc = irq_sources[irq];
|
||||||
if (isrc != NULL && isrc->isrc_type == ARM_ISRCT_FDT &&
|
if (isrc != NULL && isrc->isrc_type == INTR_ISRCT_FDT &&
|
||||||
isrc->isrc_xref == xref && isrc->isrc_ncells == ncells &&
|
isrc->isrc_xref == xref && isrc->isrc_ncells == ncells &&
|
||||||
memcmp(isrc->isrc_cells, cells, cellsize) == 0)
|
memcmp(isrc->isrc_cells, cells, cellsize) == 0)
|
||||||
return (isrc);
|
return (isrc);
|
||||||
@ -536,9 +536,9 @@ isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
|
|||||||
* associated with mapped interrupt source.
|
* associated with mapped interrupt source.
|
||||||
*/
|
*/
|
||||||
u_int
|
u_int
|
||||||
arm_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
|
intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc, *new_isrc;
|
struct intr_irqsrc *isrc, *new_isrc;
|
||||||
u_int cellsize;
|
u_int cellsize;
|
||||||
intptr_t xref;
|
intptr_t xref;
|
||||||
int error;
|
int error;
|
||||||
@ -546,7 +546,7 @@ arm_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
|
|||||||
xref = (intptr_t)node; /* It's so simple for now. */
|
xref = (intptr_t)node; /* It's so simple for now. */
|
||||||
|
|
||||||
cellsize = ncells * sizeof(*cells);
|
cellsize = ncells * sizeof(*cells);
|
||||||
new_isrc = isrc_alloc(ARM_ISRCT_FDT, cellsize);
|
new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize);
|
||||||
|
|
||||||
mtx_lock(&isrc_table_lock);
|
mtx_lock(&isrc_table_lock);
|
||||||
isrc = isrc_fdt_lookup(xref, cells, ncells);
|
isrc = isrc_fdt_lookup(xref, cells, ncells);
|
||||||
@ -576,13 +576,13 @@ arm_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
|
|||||||
* Register interrupt source into interrupt controller.
|
* Register interrupt source into interrupt controller.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
isrc_register(struct arm_irqsrc *isrc)
|
isrc_register(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
boolean_t is_percpu;
|
boolean_t is_percpu;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (isrc->isrc_flags & ARM_ISRCF_REGISTERED)
|
if (isrc->isrc_flags & INTR_ISRCF_REGISTERED)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (isrc->isrc_dev == NULL) {
|
if (isrc->isrc_dev == NULL) {
|
||||||
@ -597,9 +597,9 @@ isrc_register(struct arm_irqsrc *isrc)
|
|||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
mtx_lock(&isrc_table_lock);
|
mtx_lock(&isrc_table_lock);
|
||||||
isrc->isrc_flags |= ARM_ISRCF_REGISTERED;
|
isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
|
||||||
if (is_percpu)
|
if (is_percpu)
|
||||||
isrc->isrc_flags |= ARM_ISRCF_PERCPU;
|
isrc->isrc_flags |= INTR_ISRCF_PERCPU;
|
||||||
isrc_update_name(isrc, NULL);
|
isrc_update_name(isrc, NULL);
|
||||||
mtx_unlock(&isrc_table_lock);
|
mtx_unlock(&isrc_table_lock);
|
||||||
return (0);
|
return (0);
|
||||||
@ -610,8 +610,8 @@ isrc_register(struct arm_irqsrc *isrc)
|
|||||||
* Setup filter into interrupt source.
|
* Setup filter into interrupt source.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
iscr_setup_filter(struct arm_irqsrc *isrc, const char *name,
|
iscr_setup_filter(struct intr_irqsrc *isrc, const char *name,
|
||||||
arm_irq_filter_t *filter, void *arg, void **cookiep)
|
intr_irq_filter_t *filter, void *arg, void **cookiep)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (filter == NULL)
|
if (filter == NULL)
|
||||||
@ -640,9 +640,9 @@ iscr_setup_filter(struct arm_irqsrc *isrc, const char *name,
|
|||||||
* Interrupt source pre_ithread method for MI interrupt framework.
|
* Interrupt source pre_ithread method for MI interrupt framework.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
arm_isrc_pre_ithread(void *arg)
|
intr_isrc_pre_ithread(void *arg)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc = arg;
|
struct intr_irqsrc *isrc = arg;
|
||||||
|
|
||||||
PIC_PRE_ITHREAD(isrc->isrc_dev, isrc);
|
PIC_PRE_ITHREAD(isrc->isrc_dev, isrc);
|
||||||
}
|
}
|
||||||
@ -651,9 +651,9 @@ arm_isrc_pre_ithread(void *arg)
|
|||||||
* Interrupt source post_ithread method for MI interrupt framework.
|
* Interrupt source post_ithread method for MI interrupt framework.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
arm_isrc_post_ithread(void *arg)
|
intr_isrc_post_ithread(void *arg)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc = arg;
|
struct intr_irqsrc *isrc = arg;
|
||||||
|
|
||||||
PIC_POST_ITHREAD(isrc->isrc_dev, isrc);
|
PIC_POST_ITHREAD(isrc->isrc_dev, isrc);
|
||||||
}
|
}
|
||||||
@ -662,9 +662,9 @@ arm_isrc_post_ithread(void *arg)
|
|||||||
* Interrupt source post_filter method for MI interrupt framework.
|
* Interrupt source post_filter method for MI interrupt framework.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
arm_isrc_post_filter(void *arg)
|
intr_isrc_post_filter(void *arg)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc = arg;
|
struct intr_irqsrc *isrc = arg;
|
||||||
|
|
||||||
PIC_POST_FILTER(isrc->isrc_dev, isrc);
|
PIC_POST_FILTER(isrc->isrc_dev, isrc);
|
||||||
}
|
}
|
||||||
@ -673,10 +673,10 @@ arm_isrc_post_filter(void *arg)
|
|||||||
* Interrupt source assign_cpu method for MI interrupt framework.
|
* Interrupt source assign_cpu method for MI interrupt framework.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
arm_isrc_assign_cpu(void *arg, int cpu)
|
intr_isrc_assign_cpu(void *arg, int cpu)
|
||||||
{
|
{
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
struct arm_irqsrc *isrc = arg;
|
struct intr_irqsrc *isrc = arg;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (isrc->isrc_dev != irq_root_dev)
|
if (isrc->isrc_dev != irq_root_dev)
|
||||||
@ -685,10 +685,10 @@ arm_isrc_assign_cpu(void *arg, int cpu)
|
|||||||
mtx_lock(&isrc_table_lock);
|
mtx_lock(&isrc_table_lock);
|
||||||
if (cpu == NOCPU) {
|
if (cpu == NOCPU) {
|
||||||
CPU_ZERO(&isrc->isrc_cpu);
|
CPU_ZERO(&isrc->isrc_cpu);
|
||||||
isrc->isrc_flags &= ~ARM_ISRCF_BOUND;
|
isrc->isrc_flags &= ~INTR_ISRCF_BOUND;
|
||||||
} else {
|
} else {
|
||||||
CPU_SETOF(cpu, &isrc->isrc_cpu);
|
CPU_SETOF(cpu, &isrc->isrc_cpu);
|
||||||
isrc->isrc_flags |= ARM_ISRCF_BOUND;
|
isrc->isrc_flags |= INTR_ISRCF_BOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -716,14 +716,14 @@ arm_isrc_assign_cpu(void *arg, int cpu)
|
|||||||
* Create interrupt event for interrupt source.
|
* Create interrupt event for interrupt source.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
isrc_event_create(struct arm_irqsrc *isrc)
|
isrc_event_create(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct intr_event *ie;
|
struct intr_event *ie;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq,
|
error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq,
|
||||||
arm_isrc_pre_ithread, arm_isrc_post_ithread, arm_isrc_post_filter,
|
intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter,
|
||||||
arm_isrc_assign_cpu, "%s:", isrc->isrc_name);
|
intr_isrc_assign_cpu, "%s:", isrc->isrc_name);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
@ -747,7 +747,7 @@ isrc_event_create(struct arm_irqsrc *isrc)
|
|||||||
* Destroy interrupt event for interrupt source.
|
* Destroy interrupt event for interrupt source.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isrc_event_destroy(struct arm_irqsrc *isrc)
|
isrc_event_destroy(struct intr_irqsrc *isrc)
|
||||||
{
|
{
|
||||||
struct intr_event *ie;
|
struct intr_event *ie;
|
||||||
|
|
||||||
@ -764,7 +764,7 @@ isrc_event_destroy(struct arm_irqsrc *isrc)
|
|||||||
* Add handler to interrupt source.
|
* Add handler to interrupt source.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
isrc_add_handler(struct arm_irqsrc *isrc, const char *name,
|
isrc_add_handler(struct intr_irqsrc *isrc, const char *name,
|
||||||
driver_filter_t filter, driver_intr_t handler, void *arg,
|
driver_filter_t filter, driver_intr_t handler, void *arg,
|
||||||
enum intr_type flags, void **cookiep)
|
enum intr_type flags, void **cookiep)
|
||||||
{
|
{
|
||||||
@ -790,10 +790,10 @@ isrc_add_handler(struct arm_irqsrc *isrc, const char *name,
|
|||||||
/*
|
/*
|
||||||
* Lookup interrupt controller locked.
|
* Lookup interrupt controller locked.
|
||||||
*/
|
*/
|
||||||
static struct arm_pic *
|
static struct intr_pic *
|
||||||
pic_lookup_locked(device_t dev, intptr_t xref)
|
pic_lookup_locked(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
|
|
||||||
mtx_assert(&pic_list_lock, MA_OWNED);
|
mtx_assert(&pic_list_lock, MA_OWNED);
|
||||||
|
|
||||||
@ -809,10 +809,10 @@ pic_lookup_locked(device_t dev, intptr_t xref)
|
|||||||
/*
|
/*
|
||||||
* Lookup interrupt controller.
|
* Lookup interrupt controller.
|
||||||
*/
|
*/
|
||||||
static struct arm_pic *
|
static struct intr_pic *
|
||||||
pic_lookup(device_t dev, intptr_t xref)
|
pic_lookup(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
|
|
||||||
mtx_lock(&pic_list_lock);
|
mtx_lock(&pic_list_lock);
|
||||||
pic = pic_lookup_locked(dev, xref);
|
pic = pic_lookup_locked(dev, xref);
|
||||||
@ -824,10 +824,10 @@ pic_lookup(device_t dev, intptr_t xref)
|
|||||||
/*
|
/*
|
||||||
* Create interrupt controller.
|
* Create interrupt controller.
|
||||||
*/
|
*/
|
||||||
static struct arm_pic *
|
static struct intr_pic *
|
||||||
pic_create(device_t dev, intptr_t xref)
|
pic_create(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
|
|
||||||
mtx_lock(&pic_list_lock);
|
mtx_lock(&pic_list_lock);
|
||||||
pic = pic_lookup_locked(dev, xref);
|
pic = pic_lookup_locked(dev, xref);
|
||||||
@ -850,7 +850,7 @@ pic_create(device_t dev, intptr_t xref)
|
|||||||
static void
|
static void
|
||||||
pic_destroy(device_t dev, intptr_t xref)
|
pic_destroy(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
|
|
||||||
mtx_lock(&pic_list_lock);
|
mtx_lock(&pic_list_lock);
|
||||||
pic = pic_lookup_locked(dev, xref);
|
pic = pic_lookup_locked(dev, xref);
|
||||||
@ -858,7 +858,7 @@ pic_destroy(device_t dev, intptr_t xref)
|
|||||||
mtx_unlock(&pic_list_lock);
|
mtx_unlock(&pic_list_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SLIST_REMOVE(&pic_list, pic, arm_pic, pic_next);
|
SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next);
|
||||||
mtx_unlock(&pic_list_lock);
|
mtx_unlock(&pic_list_lock);
|
||||||
|
|
||||||
free(pic, M_INTRNG);
|
free(pic, M_INTRNG);
|
||||||
@ -868,9 +868,9 @@ pic_destroy(device_t dev, intptr_t xref)
|
|||||||
* Register interrupt controller.
|
* Register interrupt controller.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
arm_pic_register(device_t dev, intptr_t xref)
|
intr_pic_register(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
struct arm_pic *pic;
|
struct intr_pic *pic;
|
||||||
|
|
||||||
pic = pic_create(dev, xref);
|
pic = pic_create(dev, xref);
|
||||||
if (pic == NULL)
|
if (pic == NULL)
|
||||||
@ -887,7 +887,7 @@ arm_pic_register(device_t dev, intptr_t xref)
|
|||||||
* Unregister interrupt controller.
|
* Unregister interrupt controller.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
arm_pic_unregister(device_t dev, intptr_t xref)
|
intr_pic_unregister(device_t dev, intptr_t xref)
|
||||||
{
|
{
|
||||||
|
|
||||||
panic("%s: not implemented", __func__);
|
panic("%s: not implemented", __func__);
|
||||||
@ -906,7 +906,7 @@ arm_pic_unregister(device_t dev, intptr_t xref)
|
|||||||
* an interrupts property and thus no explicit interrupt parent."
|
* an interrupts property and thus no explicit interrupt parent."
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter,
|
intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
|
||||||
void *arg, u_int ipicount)
|
void *arg, u_int ipicount)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@ -924,14 +924,14 @@ arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter,
|
|||||||
/*
|
/*
|
||||||
* Only one interrupt controllers could be on the root for now.
|
* Only one interrupt controllers could be on the root for now.
|
||||||
* Note that we further suppose that there is not threaded interrupt
|
* Note that we further suppose that there is not threaded interrupt
|
||||||
* routine (handler) on the root. See arm_irq_handler().
|
* routine (handler) on the root. See intr_irq_handler().
|
||||||
*/
|
*/
|
||||||
if (irq_root_dev != NULL) {
|
if (irq_root_dev != NULL) {
|
||||||
device_printf(dev, "another root already set\n");
|
device_printf(dev, "another root already set\n");
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
rootirq = arm_namespace_map_irq(device_get_parent(dev), 0, 0);
|
rootirq = intr_namespace_map_irq(device_get_parent(dev), 0, 0);
|
||||||
if (rootirq == IRQ_INVALID) {
|
if (rootirq == IRQ_INVALID) {
|
||||||
device_printf(dev, "failed to map an irq for the root pic\n");
|
device_printf(dev, "failed to map an irq for the root pic\n");
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
@ -941,9 +941,9 @@ arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter,
|
|||||||
irq_root_isrc = isrc_lookup(rootirq);
|
irq_root_isrc = isrc_lookup(rootirq);
|
||||||
|
|
||||||
/* XXX "register" with the PIC. We are the "pic" here, so fake it. */
|
/* XXX "register" with the PIC. We are the "pic" here, so fake it. */
|
||||||
irq_root_isrc->isrc_flags |= ARM_ISRCF_REGISTERED;
|
irq_root_isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
|
||||||
|
|
||||||
error = arm_irq_add_handler(device_get_parent(dev),
|
error = intr_irq_add_handler(device_get_parent(dev),
|
||||||
(void*)filter, NULL, arg, rootirq, INTR_TYPE_CLK, NULL);
|
(void*)filter, NULL, arg, rootirq, INTR_TYPE_CLK, NULL);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
device_printf(dev, "failed to install root pic handler\n");
|
device_printf(dev, "failed to install root pic handler\n");
|
||||||
@ -959,11 +959,11 @@ arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
arm_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
|
intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
|
||||||
void *arg, u_int irq, int flags, void **cookiep)
|
void *arg, u_int irq, int flags, void **cookiep)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
name = device_get_nameunit(dev);
|
name = device_get_nameunit(dev);
|
||||||
@ -977,7 +977,7 @@ arm_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
|
|||||||
* chained, MI interrupt framework is called only in leaf controller.
|
* chained, MI interrupt framework is called only in leaf controller.
|
||||||
*
|
*
|
||||||
* Note that root interrupt controller routine is served as well,
|
* Note that root interrupt controller routine is served as well,
|
||||||
* however in arm_irq_handler(), i.e. main system dispatch routine.
|
* however in intr_irq_handler(), i.e. main system dispatch routine.
|
||||||
*/
|
*/
|
||||||
if (flags & INTR_SOLO && hand != NULL) {
|
if (flags & INTR_SOLO && hand != NULL) {
|
||||||
debugf("irq %u cannot solo on %s\n", irq, name);
|
debugf("irq %u cannot solo on %s\n", irq, name);
|
||||||
@ -999,7 +999,7 @@ arm_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
|
|||||||
|
|
||||||
#ifdef INTR_SOLO
|
#ifdef INTR_SOLO
|
||||||
if (flags & INTR_SOLO) {
|
if (flags & INTR_SOLO) {
|
||||||
error = iscr_setup_filter(isrc, name, (arm_irq_filter_t *)filt,
|
error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt,
|
||||||
arg, cookiep);
|
arg, cookiep);
|
||||||
debugf("irq %u setup filter error %d on %s\n", irq, error,
|
debugf("irq %u setup filter error %d on %s\n", irq, error,
|
||||||
name);
|
name);
|
||||||
@ -1024,9 +1024,9 @@ arm_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
arm_irq_remove_handler(device_t dev, u_int irq, void *cookie)
|
intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
isrc = isrc_lookup(irq);
|
isrc = isrc_lookup(irq);
|
||||||
@ -1066,9 +1066,9 @@ arm_irq_remove_handler(device_t dev, u_int irq, void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
arm_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
|
intr_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
isrc = isrc_lookup(irq);
|
isrc = isrc_lookup(irq);
|
||||||
if (isrc == NULL)
|
if (isrc == NULL)
|
||||||
@ -1090,9 +1090,9 @@ arm_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
arm_irq_describe(u_int irq, void *cookie, const char *descr)
|
intr_irq_describe(u_int irq, void *cookie, const char *descr)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
isrc = isrc_lookup(irq);
|
isrc = isrc_lookup(irq);
|
||||||
@ -1120,16 +1120,16 @@ arm_irq_describe(u_int irq, void *cookie, const char *descr)
|
|||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
int
|
int
|
||||||
arm_irq_bind(u_int irq, int cpu)
|
intr_irq_bind(u_int irq, int cpu)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
isrc = isrc_lookup(irq);
|
isrc = isrc_lookup(irq);
|
||||||
if (isrc == NULL || isrc->isrc_handlers == 0)
|
if (isrc == NULL || isrc->isrc_handlers == 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
if (isrc->isrc_filter != NULL)
|
if (isrc->isrc_filter != NULL)
|
||||||
return (arm_isrc_assign_cpu(isrc, cpu));
|
return (intr_isrc_assign_cpu(isrc, cpu));
|
||||||
|
|
||||||
return (intr_event_bind(isrc->isrc_event, cpu));
|
return (intr_event_bind(isrc->isrc_event, cpu));
|
||||||
}
|
}
|
||||||
@ -1139,7 +1139,7 @@ arm_irq_bind(u_int irq, int cpu)
|
|||||||
* For now just returns the next CPU according to round-robin.
|
* For now just returns the next CPU according to round-robin.
|
||||||
*/
|
*/
|
||||||
u_int
|
u_int
|
||||||
arm_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask)
|
intr_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!irq_assign_cpu || mp_ncpus == 1)
|
if (!irq_assign_cpu || mp_ncpus == 1)
|
||||||
@ -1158,9 +1158,9 @@ arm_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask)
|
|||||||
* CPUs once the AP's have been launched.
|
* CPUs once the AP's have been launched.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
arm_irq_shuffle(void *arg __unused)
|
intr_irq_shuffle(void *arg __unused)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (mp_ncpus == 1)
|
if (mp_ncpus == 1)
|
||||||
@ -1171,15 +1171,15 @@ arm_irq_shuffle(void *arg __unused)
|
|||||||
for (i = 0; i < NIRQ; i++) {
|
for (i = 0; i < NIRQ; i++) {
|
||||||
isrc = irq_sources[i];
|
isrc = irq_sources[i];
|
||||||
if (isrc == NULL || isrc->isrc_handlers == 0 ||
|
if (isrc == NULL || isrc->isrc_handlers == 0 ||
|
||||||
isrc->isrc_flags & ARM_ISRCF_PERCPU)
|
isrc->isrc_flags & INTR_ISRCF_PERCPU)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isrc->isrc_event != NULL &&
|
if (isrc->isrc_event != NULL &&
|
||||||
isrc->isrc_flags & ARM_ISRCF_BOUND &&
|
isrc->isrc_flags & INTR_ISRCF_BOUND &&
|
||||||
isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1)
|
isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1)
|
||||||
panic("%s: CPU inconsistency", __func__);
|
panic("%s: CPU inconsistency", __func__);
|
||||||
|
|
||||||
if ((isrc->isrc_flags & ARM_ISRCF_BOUND) == 0)
|
if ((isrc->isrc_flags & INTR_ISRCF_BOUND) == 0)
|
||||||
CPU_ZERO(&isrc->isrc_cpu); /* start again */
|
CPU_ZERO(&isrc->isrc_cpu); /* start again */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1192,11 +1192,11 @@ arm_irq_shuffle(void *arg __unused)
|
|||||||
}
|
}
|
||||||
mtx_unlock(&isrc_table_lock);
|
mtx_unlock(&isrc_table_lock);
|
||||||
}
|
}
|
||||||
SYSINIT(arm_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, arm_irq_shuffle, NULL);
|
SYSINIT(intr_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, intr_irq_shuffle, NULL);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
u_int
|
u_int
|
||||||
arm_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
|
intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (PCPU_GET(cpuid));
|
return (PCPU_GET(cpuid));
|
||||||
@ -1209,91 +1209,28 @@ dosoftints(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* arm_irq_memory_barrier()
|
|
||||||
*
|
|
||||||
* Ensure all writes to device memory have reached devices before proceeding.
|
|
||||||
*
|
|
||||||
* This is intended to be called from the post-filter and post-thread routines
|
|
||||||
* of an interrupt controller implementation. A peripheral device driver should
|
|
||||||
* use bus_space_barrier() if it needs to ensure a write has reached the
|
|
||||||
* hardware for some reason other than clearing interrupt conditions.
|
|
||||||
*
|
|
||||||
* The need for this function arises from the ARM weak memory ordering model.
|
|
||||||
* Writes to locations mapped with the Device attribute bypass any caches, but
|
|
||||||
* are buffered. Multiple writes to the same device will be observed by that
|
|
||||||
* device in the order issued by the cpu. Writes to different devices may
|
|
||||||
* appear at those devices in a different order than issued by the cpu. That
|
|
||||||
* is, if the cpu writes to device A then device B, the write to device B could
|
|
||||||
* complete before the write to device A.
|
|
||||||
*
|
|
||||||
* Consider a typical device interrupt handler which services the interrupt and
|
|
||||||
* writes to a device status-acknowledge register to clear the interrupt before
|
|
||||||
* returning. That write is posted to the L2 controller which "immediately"
|
|
||||||
* places it in a store buffer and automatically drains that buffer. This can
|
|
||||||
* be less immediate than you'd think... There may be no free slots in the store
|
|
||||||
* buffers, so an existing buffer has to be drained first to make room. The
|
|
||||||
* target bus may be busy with other traffic (such as DMA for various devices),
|
|
||||||
* delaying the drain of the store buffer for some indeterminate time. While
|
|
||||||
* all this delay is happening, execution proceeds on the CPU, unwinding its way
|
|
||||||
* out of the interrupt call stack to the point where the interrupt driver code
|
|
||||||
* is ready to EOI and unmask the interrupt. The interrupt controller may be
|
|
||||||
* accessed via a faster bus than the hardware whose handler just ran; the write
|
|
||||||
* to unmask and EOI the interrupt may complete quickly while the device write
|
|
||||||
* to ack and clear the interrupt source is still lingering in a store buffer
|
|
||||||
* waiting for access to a slower bus. With the interrupt unmasked at the
|
|
||||||
* interrupt controller but still active at the device, as soon as interrupts
|
|
||||||
* are enabled on the core the device re-interrupts immediately: now you've got
|
|
||||||
* a spurious interrupt on your hands.
|
|
||||||
*
|
|
||||||
* The right way to fix this problem is for every device driver to use the
|
|
||||||
* proper bus_space_barrier() calls in its interrupt handler. For ARM a single
|
|
||||||
* barrier call at the end of the handler would work. This would have to be
|
|
||||||
* done to every driver in the system, not just arm-specific drivers.
|
|
||||||
*
|
|
||||||
* Another potential fix is to map all device memory as Strongly-Ordered rather
|
|
||||||
* than Device memory, which takes the store buffers out of the picture. This
|
|
||||||
* has a pretty big impact on overall system performance, because each strongly
|
|
||||||
* ordered memory access causes all L2 store buffers to be drained.
|
|
||||||
*
|
|
||||||
* A compromise solution is to have the interrupt controller implementation call
|
|
||||||
* this function to establish a barrier between writes to the interrupt-source
|
|
||||||
* device and writes to the interrupt controller device.
|
|
||||||
*
|
|
||||||
* This takes the interrupt number as an argument, and currently doesn't use it.
|
|
||||||
* The plan is that maybe some day there is a way to flag certain interrupts as
|
|
||||||
* "memory barrier safe" and we can avoid this overhead with them.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
arm_irq_memory_barrier(uintptr_t irq)
|
|
||||||
{
|
|
||||||
|
|
||||||
dsb();
|
|
||||||
cpu_l2cache_drain_writebuf();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
/*
|
/*
|
||||||
* Lookup IPI source.
|
* Lookup IPI source.
|
||||||
*/
|
*/
|
||||||
static struct arm_irqsrc *
|
static struct intr_irqsrc *
|
||||||
arm_ipi_lookup(u_int ipi)
|
intr_ipi_lookup(u_int ipi)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ipi >= ARM_IPI_COUNT)
|
if (ipi >= INTR_IPI_COUNT)
|
||||||
panic("%s: no such IPI %u", __func__, ipi);
|
panic("%s: no such IPI %u", __func__, ipi);
|
||||||
|
|
||||||
return (&ipi_sources[ipi]);
|
return (&ipi_sources[ipi]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARM interrupt controller dispatch function for IPIs. It should
|
* interrupt controller dispatch function for IPIs. It should
|
||||||
* be called straight from the interrupt controller, when associated
|
* be called straight from the interrupt controller, when associated
|
||||||
* interrupt source is learned. Or from anybody who has an interrupt
|
* interrupt source is learned. Or from anybody who has an interrupt
|
||||||
* source mapped.
|
* source mapped.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
arm_ipi_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf)
|
intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
|
||||||
{
|
{
|
||||||
void *arg;
|
void *arg;
|
||||||
|
|
||||||
@ -1315,18 +1252,18 @@ arm_ipi_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf)
|
|||||||
* Not SMP coherent.
|
* Not SMP coherent.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ipi_map(struct arm_irqsrc *isrc, u_int ipi)
|
ipi_map(struct intr_irqsrc *isrc, u_int ipi)
|
||||||
{
|
{
|
||||||
boolean_t is_percpu;
|
boolean_t is_percpu;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (ipi >= ARM_IPI_COUNT)
|
if (ipi >= INTR_IPI_COUNT)
|
||||||
panic("%s: no such IPI %u", __func__, ipi);
|
panic("%s: no such IPI %u", __func__, ipi);
|
||||||
|
|
||||||
KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
|
KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
|
||||||
|
|
||||||
isrc->isrc_type = ARM_ISRCT_NAMESPACE;
|
isrc->isrc_type = INTR_ISRCT_NAMESPACE;
|
||||||
isrc->isrc_nspc_type = ARM_IRQ_NSPC_IPI;
|
isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI;
|
||||||
isrc->isrc_nspc_num = ipi_next_num;
|
isrc->isrc_nspc_num = ipi_next_num;
|
||||||
|
|
||||||
error = PIC_REGISTER(irq_root_dev, isrc, &is_percpu);
|
error = PIC_REGISTER(irq_root_dev, isrc, &is_percpu);
|
||||||
@ -1347,21 +1284,21 @@ ipi_map(struct arm_irqsrc *isrc, u_int ipi)
|
|||||||
* Note that there could be more ways how to send and receive IPIs
|
* Note that there could be more ways how to send and receive IPIs
|
||||||
* on a platform like fast interrupts for example. In that case,
|
* on a platform like fast interrupts for example. In that case,
|
||||||
* one can call this function with ASIF_NOALLOC flag set and then
|
* one can call this function with ASIF_NOALLOC flag set and then
|
||||||
* call arm_ipi_dispatch() when appropriate.
|
* call intr_ipi_dispatch() when appropriate.
|
||||||
*
|
*
|
||||||
* Not SMP coherent.
|
* Not SMP coherent.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
arm_ipi_set_handler(u_int ipi, const char *name, arm_ipi_filter_t *filter,
|
intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
|
||||||
void *arg, u_int flags)
|
void *arg, u_int flags)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (filter == NULL)
|
if (filter == NULL)
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
|
||||||
isrc = arm_ipi_lookup(ipi);
|
isrc = intr_ipi_lookup(ipi);
|
||||||
if (isrc->isrc_ipifilter != NULL)
|
if (isrc->isrc_ipifilter != NULL)
|
||||||
return (EEXIST);
|
return (EEXIST);
|
||||||
|
|
||||||
@ -1391,9 +1328,9 @@ arm_ipi_set_handler(u_int ipi, const char *name, arm_ipi_filter_t *filter,
|
|||||||
void
|
void
|
||||||
pic_ipi_send(cpuset_t cpus, u_int ipi)
|
pic_ipi_send(cpuset_t cpus, u_int ipi)
|
||||||
{
|
{
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
isrc = arm_ipi_lookup(ipi);
|
isrc = intr_ipi_lookup(ipi);
|
||||||
|
|
||||||
KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
|
KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__));
|
||||||
PIC_IPI_SEND(irq_root_dev, isrc, cpus);
|
PIC_IPI_SEND(irq_root_dev, isrc, cpus);
|
||||||
@ -1403,7 +1340,7 @@ pic_ipi_send(cpuset_t cpus, u_int ipi)
|
|||||||
* Init interrupt controller on another CPU.
|
* Init interrupt controller on another CPU.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
arm_pic_init_secondary(void)
|
intr_pic_init_secondary(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1421,7 +1358,7 @@ arm_pic_init_secondary(void)
|
|||||||
DB_SHOW_COMMAND(irqs, db_show_irqs)
|
DB_SHOW_COMMAND(irqs, db_show_irqs)
|
||||||
{
|
{
|
||||||
u_int i, irqsum;
|
u_int i, irqsum;
|
||||||
struct arm_irqsrc *isrc;
|
struct intr_irqsrc *isrc;
|
||||||
|
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
for (i = 0; i <= mp_maxid; i++) {
|
for (i = 0; i <= mp_maxid; i++) {
|
||||||
@ -1430,8 +1367,8 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
|
|||||||
|
|
||||||
pc = pcpu_find(i);
|
pc = pcpu_find(i);
|
||||||
if (pc != NULL) {
|
if (pc != NULL) {
|
||||||
for (ipisum = 0, ipi = 0; ipi < ARM_IPI_COUNT; ipi++) {
|
for (ipisum = 0, ipi = 0; ipi < INTR_IPI_COUNT; ipi++) {
|
||||||
isrc = arm_ipi_lookup(ipi);
|
isrc = intr_ipi_lookup(ipi);
|
||||||
if (isrc->isrc_count != NULL)
|
if (isrc->isrc_count != NULL)
|
||||||
ipisum += isrc->isrc_count[i];
|
ipisum += isrc->isrc_count[i];
|
||||||
}
|
}
|
||||||
@ -1449,7 +1386,7 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
|
|||||||
|
|
||||||
db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
|
db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
|
||||||
isrc->isrc_name, isrc->isrc_cpu.__bits[0],
|
isrc->isrc_name, isrc->isrc_cpu.__bits[0],
|
||||||
isrc->isrc_flags & ARM_ISRCF_BOUND ? " (bound)" : "",
|
isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "",
|
||||||
isrc->isrc_count[0]);
|
isrc->isrc_count[0]);
|
||||||
irqsum += isrc->isrc_count[0];
|
irqsum += isrc->isrc_count[0];
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user