powerpc: Add opaque 'private data' to interrupt vectors

The XICS and XIVE need extra data beyond irq and vector.  Rather than
performing a separate search, it's better for the general interrupt facility
to hold a private pointer, since the search already must be done anyway at
that level.
This commit is contained in:
Justin Hibbits 2019-01-12 22:05:42 +00:00
parent 5d031e332f
commit 56505ec016
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342975
9 changed files with 110 additions and 109 deletions

View File

@ -75,14 +75,14 @@ int openpic_common_attach(device_t, uint32_t);
/*
* PIC interface.
*/
void openpic_bind(device_t dev, u_int irq, cpuset_t cpumask);
void openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **);
void openpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity);
void openpic_dispatch(device_t, struct trapframe *);
void openpic_enable(device_t, u_int, u_int);
void openpic_eoi(device_t, u_int);
void openpic_enable(device_t, u_int, u_int, void **);
void openpic_eoi(device_t, u_int, void *);
void openpic_ipi(device_t, u_int);
void openpic_mask(device_t, u_int);
void openpic_unmask(device_t, u_int);
void openpic_mask(device_t, u_int, void *);
void openpic_unmask(device_t, u_int, void *);
int openpic_suspend(device_t dev);
int openpic_resume(device_t dev);

View File

@ -512,9 +512,10 @@ static int openpic_cpcht_probe(device_t);
static int openpic_cpcht_attach(device_t);
static void openpic_cpcht_config(device_t, u_int irq,
enum intr_trigger trig, enum intr_polarity pol);
static void openpic_cpcht_enable(device_t, u_int irq, u_int vector);
static void openpic_cpcht_unmask(device_t, u_int irq);
static void openpic_cpcht_eoi(device_t, u_int irq);
static void openpic_cpcht_enable(device_t, u_int irq, u_int vector,
void **priv);
static void openpic_cpcht_unmask(device_t, u_int irq, void *priv);
static void openpic_cpcht_eoi(device_t, u_int irq, void *priv);
static device_method_t openpic_cpcht_methods[] = {
/* Device interface */
@ -649,12 +650,12 @@ openpic_cpcht_config(device_t dev, u_int irq, enum intr_trigger trig,
}
static void
openpic_cpcht_enable(device_t dev, u_int irq, u_int vec)
openpic_cpcht_enable(device_t dev, u_int irq, u_int vec, void **priv)
{
struct openpic_cpcht_softc *sc;
uint32_t ht_irq;
openpic_enable(dev, irq, vec);
openpic_enable(dev, irq, vec, priv);
sc = device_get_softc(dev);
@ -674,16 +675,16 @@ openpic_cpcht_enable(device_t dev, u_int irq, u_int vec)
mtx_unlock_spin(&sc->sc_ht_mtx);
}
openpic_cpcht_eoi(dev, irq);
openpic_cpcht_eoi(dev, irq, *priv);
}
static void
openpic_cpcht_unmask(device_t dev, u_int irq)
openpic_cpcht_unmask(device_t dev, u_int irq, void *priv)
{
struct openpic_cpcht_softc *sc;
uint32_t ht_irq;
openpic_unmask(dev, irq);
openpic_unmask(dev, irq, priv);
sc = device_get_softc(dev);
@ -703,11 +704,11 @@ openpic_cpcht_unmask(device_t dev, u_int irq)
mtx_unlock_spin(&sc->sc_ht_mtx);
}
openpic_cpcht_eoi(dev, irq);
openpic_cpcht_eoi(dev, irq, priv);
}
static void
openpic_cpcht_eoi(device_t dev, u_int irq)
openpic_cpcht_eoi(device_t dev, u_int irq, void *priv)
{
struct openpic_cpcht_softc *sc;
uint32_t off, mask;
@ -737,5 +738,5 @@ openpic_cpcht_eoi(device_t dev, u_int irq)
}
}
openpic_eoi(dev, irq);
openpic_eoi(dev, irq, priv);
}

View File

@ -66,11 +66,11 @@ static int hrowpic_probe(device_t);
static int hrowpic_attach(device_t);
static void hrowpic_dispatch(device_t, struct trapframe *);
static void hrowpic_enable(device_t, u_int, u_int);
static void hrowpic_eoi(device_t, u_int);
static void hrowpic_enable(device_t, u_int, u_int, void **);
static void hrowpic_eoi(device_t, u_int, void *);
static void hrowpic_ipi(device_t, u_int);
static void hrowpic_mask(device_t, u_int);
static void hrowpic_unmask(device_t, u_int);
static void hrowpic_mask(device_t, u_int, void *);
static void hrowpic_unmask(device_t, u_int, void *);
static device_method_t hrowpic_methods[] = {
/* Device interface */
@ -237,7 +237,7 @@ hrowpic_dispatch(device_t dev, struct trapframe *tf)
}
static void
hrowpic_enable(device_t dev, u_int irq, u_int vector)
hrowpic_enable(device_t dev, u_int irq, u_int vector, void **priv __unused)
{
struct hrowpic_softc *sc;
@ -247,7 +247,7 @@ hrowpic_enable(device_t dev, u_int irq, u_int vector)
}
static void
hrowpic_eoi(device_t dev, u_int irq)
hrowpic_eoi(device_t dev, u_int irq, void *priv __unused)
{
struct hrowpic_softc *sc;
int bank;
@ -264,7 +264,7 @@ hrowpic_ipi(device_t dev, u_int irq)
}
static void
hrowpic_mask(device_t dev, u_int irq)
hrowpic_mask(device_t dev, u_int irq, void *priv __unused)
{
struct hrowpic_softc *sc;
@ -273,7 +273,7 @@ hrowpic_mask(device_t dev, u_int irq)
}
static void
hrowpic_unmask(device_t dev, u_int irq)
hrowpic_unmask(device_t dev, u_int irq, void *priv __unused)
{
struct hrowpic_softc *sc;

View File

@ -93,8 +93,8 @@ static int opalpci_route_interrupt(device_t bus, device_t dev, int pin);
/*
* MSI PIC interface.
*/
static void opalpic_pic_enable(device_t dev, u_int irq, u_int vector);
static void opalpic_pic_eoi(device_t dev, u_int irq);
static void opalpic_pic_enable(device_t dev, u_int irq, u_int vector, void **);
static void opalpic_pic_eoi(device_t dev, u_int irq, void *);
/* Bus interface */
static bus_dma_tag_t opalpci_get_dma_tag(device_t dev, device_t child);
@ -675,22 +675,22 @@ opalpci_map_msi(device_t dev, device_t child, int irq, uint64_t *addr,
}
static void
opalpic_pic_enable(device_t dev, u_int irq, u_int vector)
opalpic_pic_enable(device_t dev, u_int irq, u_int vector, void **priv)
{
struct opalpci_softc *sc = device_get_softc(dev);
PIC_ENABLE(root_pic, irq, vector);
opal_call(OPAL_PCI_MSI_EOI, sc->phb_id, irq);
PIC_ENABLE(root_pic, irq, vector, priv);
opal_call(OPAL_PCI_MSI_EOI, sc->phb_id, irq, priv);
}
static void opalpic_pic_eoi(device_t dev, u_int irq)
static void opalpic_pic_eoi(device_t dev, u_int irq, void *priv)
{
struct opalpci_softc *sc;
sc = device_get_softc(dev);
opal_call(OPAL_PCI_MSI_EOI, sc->phb_id, irq);
PIC_EOI(root_pic, irq);
PIC_EOI(root_pic, irq, priv);
}
static bus_dma_tag_t

View File

@ -96,6 +96,7 @@ static MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
struct powerpc_intr {
struct intr_event *event;
long *cntp;
void *priv; /* PIC-private data */
u_int irq;
device_t pic;
u_int intline;
@ -158,7 +159,7 @@ smp_intr_init(void *dummy __unused)
for (vector = 0; vector < nvectors; vector++) {
i = powerpc_intrs[vector];
if (i != NULL && i->event != NULL && i->pic == root_pic)
PIC_BIND(i->pic, i->intline, i->cpu);
PIC_BIND(i->pic, i->intline, i->cpu, &i->priv);
}
}
SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
@ -281,7 +282,7 @@ powerpc_intr_eoi(void *arg)
{
struct powerpc_intr *i = arg;
PIC_EOI(i->pic, i->intline);
PIC_EOI(i->pic, i->intline, i->priv);
}
static void
@ -289,8 +290,8 @@ powerpc_intr_pre_ithread(void *arg)
{
struct powerpc_intr *i = arg;
PIC_MASK(i->pic, i->intline);
PIC_EOI(i->pic, i->intline);
PIC_MASK(i->pic, i->intline, i->priv);
PIC_EOI(i->pic, i->intline, i->priv);
}
static void
@ -298,7 +299,7 @@ powerpc_intr_post_ithread(void *arg)
{
struct powerpc_intr *i = arg;
PIC_UNMASK(i->pic, i->intline);
PIC_UNMASK(i->pic, i->intline, i->priv);
}
static int
@ -313,7 +314,7 @@ powerpc_assign_intr_cpu(void *arg, int cpu)
CPU_SETOF(cpu, &i->cpu);
if (!cold && i->pic != NULL && i->pic == root_pic)
PIC_BIND(i->pic, i->intline, i->cpu);
PIC_BIND(i->pic, i->intline, i->cpu, &i->priv);
return (0);
#else
@ -465,7 +466,7 @@ powerpc_enable_intr(void)
PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
if (i->event != NULL)
PIC_ENABLE(i->pic, i->intline, vector);
PIC_ENABLE(i->pic, i->intline, vector, &i->priv);
}
return (0);
@ -512,10 +513,11 @@ powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
if (i->pic == root_pic)
PIC_BIND(i->pic, i->intline, i->cpu);
PIC_BIND(i->pic, i->intline, i->cpu, &i->priv);
if (enable)
PIC_ENABLE(i->pic, i->intline, i->vector);
PIC_ENABLE(i->pic, i->intline, i->vector,
&i->priv);
}
}
return (error);
@ -602,7 +604,7 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
* This prevents races in IPI handling.
*/
if (i->ipi)
PIC_EOI(i->pic, i->intline);
PIC_EOI(i->pic, i->intline, i->priv);
if (intr_event_handle(ie, tf) != 0) {
goto stray;
@ -619,7 +621,7 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
}
}
if (i != NULL)
PIC_MASK(i->pic, i->intline);
PIC_MASK(i->pic, i->intline, i->priv);
}
void
@ -631,7 +633,7 @@ powerpc_intr_mask(u_int irq)
if (i == NULL || i->pic == NULL)
return;
PIC_MASK(i->pic, i->intline);
PIC_MASK(i->pic, i->intline, i->priv);
}
void
@ -643,5 +645,5 @@ powerpc_intr_unmask(u_int irq)
if (i == NULL || i->pic == NULL)
return;
PIC_UNMASK(i->pic, i->intline);
PIC_UNMASK(i->pic, i->intline, i->priv);
}

View File

@ -233,7 +233,7 @@ openpic_common_attach(device_t dev, uint32_t node)
*/
void
openpic_bind(device_t dev, u_int irq, cpuset_t cpumask)
openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv __unused)
{
struct openpic_softc *sc;
@ -302,7 +302,7 @@ openpic_dispatch(device_t dev, struct trapframe *tf)
}
void
openpic_enable(device_t dev, u_int irq, u_int vector)
openpic_enable(device_t dev, u_int irq, u_int vector, void **priv __unused)
{
struct openpic_softc *sc;
uint32_t x;
@ -322,7 +322,7 @@ openpic_enable(device_t dev, u_int irq, u_int vector)
}
void
openpic_eoi(device_t dev, u_int irq __unused)
openpic_eoi(device_t dev, u_int irq __unused, void *priv __unused)
{
struct openpic_softc *sc;
u_int cpuid;
@ -348,7 +348,7 @@ openpic_ipi(device_t dev, u_int cpu)
}
void
openpic_mask(device_t dev, u_int irq)
openpic_mask(device_t dev, u_int irq, void *priv __unused)
{
struct openpic_softc *sc;
uint32_t x;
@ -366,7 +366,7 @@ openpic_mask(device_t dev, u_int irq)
}
void
openpic_unmask(device_t dev, u_int irq)
openpic_unmask(device_t dev, u_int irq, void *priv __unused)
{
struct openpic_softc *sc;
uint32_t x;

View File

@ -48,6 +48,7 @@ METHOD void bind {
device_t dev;
u_int irq;
cpuset_t cpumask;
void **priv;
};
METHOD void translate_code {
@ -74,11 +75,13 @@ METHOD void enable {
device_t dev;
u_int irq;
u_int vector;
void **priv;
};
METHOD void eoi {
device_t dev;
u_int irq;
void *priv;
};
METHOD void ipi {
@ -89,10 +92,12 @@ METHOD void ipi {
METHOD void mask {
device_t dev;
u_int irq;
void *priv;
};
METHOD void unmask {
device_t dev;
u_int irq;
void *priv;
};

View File

@ -51,11 +51,11 @@ static int ps3pic_probe(device_t);
static int ps3pic_attach(device_t);
static void ps3pic_dispatch(device_t, struct trapframe *);
static void ps3pic_enable(device_t, u_int, u_int);
static void ps3pic_eoi(device_t, u_int);
static void ps3pic_enable(device_t, u_int, u_int, void **);
static void ps3pic_eoi(device_t, u_int, void *);
static void ps3pic_ipi(device_t, u_int);
static void ps3pic_mask(device_t, u_int);
static void ps3pic_unmask(device_t, u_int);
static void ps3pic_mask(device_t, u_int, void *);
static void ps3pic_unmask(device_t, u_int, void *);
struct ps3pic_softc {
volatile uint64_t *bitmap_thread0;
@ -183,18 +183,18 @@ ps3pic_dispatch(device_t dev, struct trapframe *tf)
}
static void
ps3pic_enable(device_t dev, u_int irq, u_int vector)
ps3pic_enable(device_t dev, u_int irq, u_int vector, void **priv)
{
struct ps3pic_softc *sc;
sc = device_get_softc(dev);
sc->sc_vector[irq] = vector;
ps3pic_unmask(dev, irq);
ps3pic_unmask(dev, irq, priv);
}
static void
ps3pic_eoi(device_t dev, u_int irq)
ps3pic_eoi(device_t dev, u_int irq, void *priv)
{
uint64_t ppe;
int thread;
@ -215,7 +215,7 @@ ps3pic_ipi(device_t dev, u_int cpu)
}
static void
ps3pic_mask(device_t dev, u_int irq)
ps3pic_mask(device_t dev, u_int irq, void *priv)
{
struct ps3pic_softc *sc;
uint64_t ppe;
@ -235,7 +235,7 @@ ps3pic_mask(device_t dev, u_int irq)
}
static void
ps3pic_unmask(device_t dev, u_int irq)
ps3pic_unmask(device_t dev, u_int irq, void *priv)
{
struct ps3pic_softc *sc;
uint64_t ppe;

View File

@ -69,13 +69,13 @@ static int xicp_attach(device_t);
static int xics_probe(device_t);
static int xics_attach(device_t);
static void xicp_bind(device_t dev, u_int irq, cpuset_t cpumask);
static void xicp_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv);
static void xicp_dispatch(device_t, struct trapframe *);
static void xicp_enable(device_t, u_int, u_int);
static void xicp_eoi(device_t, u_int);
static void xicp_enable(device_t, u_int, u_int, void **priv);
static void xicp_eoi(device_t, u_int, void *priv);
static void xicp_ipi(device_t, u_int);
static void xicp_mask(device_t, u_int);
static void xicp_unmask(device_t, u_int);
static void xicp_mask(device_t, u_int, void *priv);
static void xicp_unmask(device_t, u_int, void *priv);
#ifdef POWERNV
void xicp_smp_cpu_startup(void);
@ -106,6 +106,12 @@ static device_method_t xics_methods[] = {
DEVMETHOD_END
};
struct xicp_intvec {
int irq;
int vector;
int cpu;
};
struct xicp_softc {
struct mtx sc_mtx;
struct resource *mem[MAXCPU];
@ -118,11 +124,7 @@ struct xicp_softc {
int ibm_set_xive;
/* XXX: inefficient -- hash table? tree? */
struct {
int irq;
int vector;
int cpu;
} intvecs[256];
struct xicp_intvec intvecs[256];
int nintvecs;
bool xics_emu;
};
@ -297,9 +299,10 @@ xics_attach(device_t dev)
*/
static void
xicp_bind(device_t dev, u_int irq, cpuset_t cpumask)
xicp_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv)
{
struct xicp_softc *sc = device_get_softc(dev);
struct xicp_intvec *iv;
cell_t status, cpu;
int ncpus, i, error;
@ -307,6 +310,11 @@ xicp_bind(device_t dev, u_int irq, cpuset_t cpumask)
if (irq == MAX_XICP_IRQS)
return;
if (*priv == NULL)
*priv = &sc->intvecs[sc->nintvecs++];
iv = *priv;
/*
* This doesn't appear to actually support affinity groups, so pick a
* random CPU.
@ -326,15 +334,7 @@ xicp_bind(device_t dev, u_int irq, cpuset_t cpumask)
}
cpu = pcpu_find(cpu)->pc_hwref;
/* XXX: super inefficient */
for (i = 0; i < sc->nintvecs; i++) {
if (sc->intvecs[i].irq == irq) {
sc->intvecs[i].cpu = cpu;
break;
}
}
KASSERT(i < sc->nintvecs, ("Binding non-configured interrupt"));
iv->cpu = cpu;
if (rtas_exists())
error = rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu,
@ -412,26 +412,30 @@ xicp_dispatch(device_t dev, struct trapframe *tf)
}
static void
xicp_enable(device_t dev, u_int irq, u_int vector)
xicp_enable(device_t dev, u_int irq, u_int vector, void **priv)
{
struct xicp_softc *sc;
struct xicp_intvec *intr;
cell_t status, cpu;
sc = device_get_softc(dev);
KASSERT(sc->nintvecs + 1 < nitems(sc->intvecs),
("Too many XICP interrupts"));
/* Bind to this CPU to start: distrib. ID is last entry in gserver# */
cpu = PCPU_GET(hwref);
mtx_lock(&sc->sc_mtx);
sc->intvecs[sc->nintvecs].irq = irq;
sc->intvecs[sc->nintvecs].vector = vector;
sc->intvecs[sc->nintvecs].cpu = cpu;
if (*priv == NULL) {
KASSERT(sc->nintvecs + 1 < nitems(sc->intvecs),
("Too many XICP interrupts"));
mtx_lock(&sc->sc_mtx);
*priv = &sc->intvecs[sc->nintvecs++];
mtx_unlock(&sc->sc_mtx);
}
intr = *priv;
intr->irq = irq;
intr->vector = vector;
intr->cpu = cpu;
mb();
sc->nintvecs++;
mtx_unlock(&sc->sc_mtx);
/* IPIs are also enabled */
if (irq == MAX_XICP_IRQS)
@ -440,7 +444,7 @@ xicp_enable(device_t dev, u_int irq, u_int vector)
if (rtas_exists()) {
rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu,
XICP_PRIORITY, &status);
xicp_unmask(dev, irq);
xicp_unmask(dev, irq, intr);
#ifdef POWERNV
} else {
status = opal_call(OPAL_SET_XIVE, irq, cpu << 2, XICP_PRIORITY);
@ -454,7 +458,7 @@ xicp_enable(device_t dev, u_int irq, u_int vector)
}
static void
xicp_eoi(device_t dev, u_int irq)
xicp_eoi(device_t dev, u_int irq, void *priv)
{
#ifdef POWERNV
struct xicp_softc *sc;
@ -500,7 +504,7 @@ xicp_ipi(device_t dev, u_int cpu)
}
static void
xicp_mask(device_t dev, u_int irq)
xicp_mask(device_t dev, u_int irq, void *priv)
{
struct xicp_softc *sc = device_get_softc(dev);
cell_t status;
@ -512,21 +516,16 @@ xicp_mask(device_t dev, u_int irq)
rtas_call_method(sc->ibm_int_off, 1, 1, irq, &status);
#ifdef POWERNV
} else {
int i;
struct xicp_intvec *ivec = priv;
for (i = 0; i < sc->nintvecs; i++) {
if (sc->intvecs[i].irq == irq) {
break;
}
}
KASSERT(i < sc->nintvecs, ("Masking unconfigured interrupt"));
opal_call(OPAL_SET_XIVE, irq, sc->intvecs[i].cpu << 2, 0xff);
KASSERT(ivec != NULL, ("Masking unconfigured interrupt"));
opal_call(OPAL_SET_XIVE, irq, ivec->cpu << 2, 0xff);
#endif
}
}
static void
xicp_unmask(device_t dev, u_int irq)
xicp_unmask(device_t dev, u_int irq, void *priv)
{
struct xicp_softc *sc = device_get_softc(dev);
cell_t status;
@ -538,16 +537,10 @@ xicp_unmask(device_t dev, u_int irq)
rtas_call_method(sc->ibm_int_on, 1, 1, irq, &status);
#ifdef POWERNV
} else {
int i;
struct xicp_intvec *ivec = priv;
for (i = 0; i < sc->nintvecs; i++) {
if (sc->intvecs[i].irq == irq) {
break;
}
}
KASSERT(i < sc->nintvecs, ("Unmasking unconfigured interrupt"));
opal_call(OPAL_SET_XIVE, irq, sc->intvecs[i].cpu << 2,
XICP_PRIORITY);
KASSERT(ivec != NULL, ("Unmasking unconfigured interrupt"));
opal_call(OPAL_SET_XIVE, irq, ivec->cpu << 2, XICP_PRIORITY);
#endif
}
}