diff options
author | marcel <marcel@FreeBSD.org> | 2010-03-27 05:40:50 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2010-03-27 05:40:50 +0000 |
commit | bf41341894ce69d389be4a581078418dc737d17f (patch) | |
tree | 17969a80680ebc6b63471f5262055a3d76b8aaa4 /sys/ia64 | |
parent | bc320635f65727a43c46fb760b9a0f1699d088d6 (diff) | |
download | FreeBSD-src-bf41341894ce69d389be4a581078418dc737d17f.zip FreeBSD-src-bf41341894ce69d389be4a581078418dc737d17f.tar.gz |
Implement interrupt to CPU binding. Assign interrupts to CPUs in a
round-robin fashion, starting with the highest priority interrupt
on the highest-numbered CPU and cycling downwards.
Diffstat (limited to 'sys/ia64')
-rw-r--r-- | sys/ia64/ia64/autoconf.c | 2 | ||||
-rw-r--r-- | sys/ia64/ia64/interrupt.c | 22 | ||||
-rw-r--r-- | sys/ia64/ia64/mp_machdep.c | 6 | ||||
-rw-r--r-- | sys/ia64/ia64/nexus.c | 14 | ||||
-rw-r--r-- | sys/ia64/ia64/sapic.c | 21 | ||||
-rw-r--r-- | sys/ia64/include/intr.h | 4 |
6 files changed, 63 insertions, 6 deletions
diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c index acac159..cf073c8 100644 --- a/sys/ia64/ia64/autoconf.c +++ b/sys/ia64/ia64/autoconf.c @@ -93,7 +93,7 @@ configure_final(void *dummy) cninit_finish(); - ia64_finalize_intr(); + ia64_enable_intr(); cold = 0; } diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index 82ac35f..adb16ec 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -122,7 +122,7 @@ ia64_xiv_reserve(u_int xiv, enum ia64_xiv_use what, ia64_ihtype ih) return (EBUSY); ia64_xiv[xiv] = what; ia64_handler[xiv] = (ih == NULL) ? ia64_ih_invalid: ih; - if (1 || bootverbose) + if (bootverbose) printf("XIV %u: use=%u, IH=%p\n", xiv, what, ih); return (0); } @@ -139,7 +139,7 @@ ia64_xiv_alloc(u_int prio, enum ia64_xiv_use what, ia64_ihtype ih) xiv0 = IA64_NXIVS - (hwprio + 1) * 16; - KASSERT(xiv0 > IA64_MIN_XIV, ("%s: min XIV", __func__)); + KASSERT(xiv0 >= IA64_MIN_XIV, ("%s: min XIV", __func__)); KASSERT(xiv0 < IA64_NXIVS, ("%s: max XIV", __func__)); xiv = xiv0; @@ -281,10 +281,24 @@ ia64_teardown_intr(void *cookie) } void -ia64_finalize_intr(void) +ia64_bind_intr(void) { + struct ia64_intr *i; + struct pcpu *pc; + u_int xiv; + int cpu; - ia64_enable_intr(); + cpu = MAXCPU; + for (xiv = IA64_NXIVS - 1; xiv >= IA64_MIN_XIV; xiv--) { + if (ia64_xiv[xiv] != IA64_XIV_IRQ) + continue; + i = ia64_intrs[xiv]; + do { + cpu = (cpu == 0) ? MAXCPU - 1 : cpu - 1; + pc = cpuid_to_pcpu[cpu]; + } while (pc == NULL || !pc->pc_md.awake); + sapic_bind_intr(i->irq, pc); + } } /* diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 60ad43a..600803a 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -382,6 +382,12 @@ cpu_mp_unleash(void *dummy) smp_active = 1; smp_started = 1; + + /* + * Now that all CPUs are up and running, bind interrupts to each of + * them. + */ + ia64_bind_intr(); } /* diff --git a/sys/ia64/ia64/nexus.c b/sys/ia64/ia64/nexus.c index 889c3d6..9885b74 100644 --- a/sys/ia64/ia64/nexus.c +++ b/sys/ia64/ia64/nexus.c @@ -50,6 +50,7 @@ #include <machine/bus.h> #include <sys/rman.h> #include <sys/interrupt.h> +#include <sys/pcpu.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -101,6 +102,7 @@ static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *); static void nexus_delete_resource(device_t, device_t, int, int); +static int nexus_bind_intr(device_t, device_t, struct resource *, int); static int nexus_config_intr(device_t, int, enum intr_trigger, enum intr_polarity); @@ -129,6 +131,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), DEVMETHOD(bus_delete_resource, nexus_delete_resource), + DEVMETHOD(bus_bind_intr, nexus_bind_intr), DEVMETHOD(bus_config_intr, nexus_config_intr), /* Clock interface */ @@ -462,6 +465,17 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, } static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + struct pcpu *pc; + + pc = cpuid_to_pcpu[cpu]; + if (pc == NULL) + return (EINVAL); + return (sapic_bind_intr(rman_get_start(irq), pc)); +} + +static int nexus_gettime(device_t dev, struct timespec *ts) { struct clocktime ct; diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c index cb8a1c3..5aa1449 100644 --- a/sys/ia64/ia64/sapic.c +++ b/sys/ia64/ia64/sapic.c @@ -35,6 +35,7 @@ #include <sys/bus.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/pcpu.h> #include <sys/sysctl.h> #include <machine/intr.h> @@ -172,6 +173,26 @@ sapic_lookup(u_int irq, u_int *vecp) int +sapic_bind_intr(u_int irq, struct pcpu *pc) +{ + struct sapic_rte rte; + struct sapic *sa; + + sa = sapic_lookup(irq, NULL); + if (sa == NULL) + return (EINVAL); + + mtx_lock_spin(&sa->sa_mtx); + sapic_read_rte(sa, irq - sa->sa_base, &rte); + rte.rte_destination_id = (pc->pc_md.lid >> 24) & 255; + rte.rte_destination_eid = (pc->pc_md.lid >> 16) & 255; + rte.rte_delivery_mode = SAPIC_DELMODE_FIXED; + sapic_write_rte(sa, irq - sa->sa_base, &rte); + mtx_unlock_spin(&sa->sa_mtx); + return (0); +} + +int sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) { struct sapic_rte rte; diff --git a/sys/ia64/include/intr.h b/sys/ia64/include/intr.h index 2ea858c..81603cf 100644 --- a/sys/ia64/include/intr.h +++ b/sys/ia64/include/intr.h @@ -35,6 +35,7 @@ #define IA64_MAX_HWPRIO 14 +struct pcpu; struct sapic; struct thread; struct trapframe; @@ -65,7 +66,7 @@ typedef u_int (ia64_ihtype)(struct thread *, u_int, struct trapframe *); extern struct ia64_pib *ia64_pib; -void ia64_finalize_intr(void); +void ia64_bind_intr(void); void ia64_handle_intr(struct trapframe *); int ia64_setup_intr(const char *, int, driver_filter_t, driver_intr_t, void *, enum intr_type, void **); @@ -76,6 +77,7 @@ u_int ia64_xiv_alloc(u_int, enum ia64_xiv_use, ia64_ihtype); int ia64_xiv_free(u_int, enum ia64_xiv_use); int ia64_xiv_reserve(u_int, enum ia64_xiv_use, ia64_ihtype); +int sapic_bind_intr(u_int, struct pcpu *); int sapic_config_intr(u_int, enum intr_trigger, enum intr_polarity); struct sapic *sapic_create(u_int, u_int, uint64_t); int sapic_enable(struct sapic *, u_int, u_int); |