summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2010-03-27 05:40:50 +0000
committermarcel <marcel@FreeBSD.org>2010-03-27 05:40:50 +0000
commitbf41341894ce69d389be4a581078418dc737d17f (patch)
tree17969a80680ebc6b63471f5262055a3d76b8aaa4 /sys/ia64
parentbc320635f65727a43c46fb760b9a0f1699d088d6 (diff)
downloadFreeBSD-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.c2
-rw-r--r--sys/ia64/ia64/interrupt.c22
-rw-r--r--sys/ia64/ia64/mp_machdep.c6
-rw-r--r--sys/ia64/ia64/nexus.c14
-rw-r--r--sys/ia64/ia64/sapic.c21
-rw-r--r--sys/ia64/include/intr.h4
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);
OpenPOWER on IntegriCloud