svn commit: r277777 - projects/powernv/powerpc/pseries
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Mon Jan 26 21:40:57 UTC 2015
Author: nwhitehorn
Date: Mon Jan 26 21:40:56 2015
New Revision: 277777
URL: https://svnweb.freebsd.org/changeset/base/277777
Log:
Provide support for multi-socket systems with multiple root interrupt
controllers when running outside of a hypervisor.
Modified:
projects/powernv/powerpc/pseries/xics.c
Modified: projects/powernv/powerpc/pseries/xics.c
==============================================================================
--- projects/powernv/powerpc/pseries/xics.c Mon Jan 26 21:24:04 2015 (r277776)
+++ projects/powernv/powerpc/pseries/xics.c Mon Jan 26 21:40:56 2015 (r277777)
@@ -82,7 +82,7 @@ static device_method_t xicp_methods[] =
DEVMETHOD(pic_mask, xicp_mask),
DEVMETHOD(pic_unmask, xicp_unmask),
- { 0, 0 },
+ DEVMETHOD_END
};
static device_method_t xics_methods[] = {
@@ -90,13 +90,15 @@ static device_method_t xics_methods[] =
DEVMETHOD(device_probe, xics_probe),
DEVMETHOD(device_attach, xics_attach),
- { 0, 0 },
+ DEVMETHOD_END
};
struct xicp_softc {
struct mtx sc_mtx;
struct resource *mem[MAXCPU];
+ int cpu_range[2];
+
int ibm_int_on;
int ibm_int_off;
int ibm_get_xive;
@@ -131,6 +133,22 @@ EARLY_DRIVER_MODULE(xicp, ofwbus, xicp_d
EARLY_DRIVER_MODULE(xics, ofwbus, xics_driver, xics_devclass, 0, 0,
BUS_PASS_INTERRUPT);
+static struct resource *
+xicp_mem_for_cpu(int cpu)
+{
+ device_t dev;
+ struct xicp_softc *sc;
+ int i;
+
+ for (i = 0; (dev = devclass_get_device(xicp_devclass, i)) != NULL; i++){
+ sc = device_get_softc(dev);
+ if (cpu >= sc->cpu_range[0] && cpu < sc->cpu_range[1])
+ return (sc->mem[cpu - sc->cpu_range[0]]);
+ }
+
+ return (NULL);
+}
+
static int
xicp_probe(device_t dev)
{
@@ -178,8 +196,18 @@ xicp_attach(device_t dev)
return (ENXIO);
}
+ if (OF_hasprop(phandle, "ibm,interrupt-server-ranges")) {
+ OF_getencprop(phandle, "ibm,interrupt-server-ranges",
+ sc->cpu_range, sizeof(sc->cpu_range));
+ device_printf(dev, "Handling CPUs %d-%d\n", sc->cpu_range[0],
+ sc->cpu_range[1]-1);
+ } else {
+ sc->cpu_range[0] = 0;
+ sc->cpu_range[1] = mp_ncpus;
+ }
+
if (mfmsr() & PSL_HV) {
- for (i = 0; i < mp_ncpus; i++) {
+ for (i = 0; i < sc->cpu_range[1] - sc->cpu_range[0]; i++) {
sc->mem[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&i, RF_ACTIVE);
if (sc->mem[i] == NULL) {
@@ -254,13 +282,20 @@ static void
xicp_dispatch(device_t dev, struct trapframe *tf)
{
struct xicp_softc *sc;
+ struct resource *regs = NULL;
uint64_t xirr, junk;
int i;
+ if (sc->mem[0])
+ regs = xicp_mem_for_cpu(PCPU_GET(cpuid));
+
+ KASSERT(sc->mem[0] == NULL || regs != NULL,
+ ("Can't find regs for CPU %d", PCPU_GET(cpuid)));
+
sc = device_get_softc(dev);
for (;;) {
- if (sc->mem[0]) {
- xirr = bus_read_4(sc->mem[PCPU_GET(cpuid)], 4);
+ if (regs) {
+ xirr = bus_read_4(regs, 4);
} else {
/* Return value in R4, use the PFT call */
phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk);
@@ -268,8 +303,8 @@ xicp_dispatch(device_t dev, struct trapf
xirr &= 0x00ffffff;
if (xirr == 0) { /* No more pending interrupts? */
- if (sc->mem[0])
- bus_write_1(sc->mem[PCPU_GET(cpuid)], 4, 0xff);
+ if (regs)
+ bus_write_1(regs, 4, 0xff);
else
phyp_hcall(H_CPPR, (uint64_t)0xff);
break;
@@ -278,8 +313,8 @@ xicp_dispatch(device_t dev, struct trapf
xirr = MAX_XICP_IRQS; /* Map to FreeBSD magic */
/* Clear IPI */
- if (sc->mem[0])
- bus_write_1(sc->mem[PCPU_GET(cpuid)], 12, 0xff);
+ if (regs)
+ bus_write_1(regs, 12, 0xff);
else
phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(cpuid)),
0xff);
@@ -343,7 +378,7 @@ xicp_eoi(device_t dev, u_int irq)
xirr = irq | (XICP_PRIORITY << 24);
if (sc->mem[0])
- bus_write_4(sc->mem[PCPU_GET(cpuid)], 4, xirr);
+ bus_write_4(xicp_mem_for_cpu(PCPU_GET(cpuid)), 4, xirr);
else
phyp_hcall(H_EOI, xirr);
}
@@ -354,7 +389,7 @@ xicp_ipi(device_t dev, u_int cpu)
struct xicp_softc *sc = device_get_softc(dev);
if (sc->mem[0])
- bus_write_1(sc->mem[cpu], 12, XICP_PRIORITY);
+ bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY);
else
phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY);
}
More information about the svn-src-projects
mailing list