powerpc: Bind IRQs to only one interrupt on QorIQ SoCs
The QorIQ SoCs don't actually support multicast interrupts, and the references state explicitly that multicast is undefined behavior. Avoid the undefined behavior by binding to only a single CPU, using a quirk to determine if this is necessary. MFC after: 3 weeks
This commit is contained in:
parent
61b38ede81
commit
4290b4b849
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343824
@ -34,6 +34,8 @@
|
||||
|
||||
#define OPENPIC_IRQMAX 256 /* h/w allows more */
|
||||
|
||||
#define OPENPIC_QUIRK_SINGLE_BIND 1 /* Bind interrupts to only 1 CPU */
|
||||
|
||||
/* Names match the macros in openpicreg.h. */
|
||||
struct openpic_timer {
|
||||
uint32_t tcnt;
|
||||
@ -55,6 +57,7 @@ struct openpic_softc {
|
||||
u_int sc_ncpu;
|
||||
u_int sc_nirq;
|
||||
int sc_psim;
|
||||
u_int sc_quirks;
|
||||
|
||||
/* Saved states. */
|
||||
uint32_t sc_saved_config;
|
||||
|
@ -128,14 +128,19 @@ openpic_ofw_probe(device_t dev)
|
||||
static int
|
||||
openpic_ofw_attach(device_t dev)
|
||||
{
|
||||
struct openpic_softc *sc;
|
||||
phandle_t xref, node;
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (OF_getencprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
|
||||
OF_getencprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
|
||||
OF_getencprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
|
||||
xref = node;
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "fsl,mpic"))
|
||||
sc->sc_quirks = OPENPIC_QUIRK_SINGLE_BIND;
|
||||
|
||||
return (openpic_common_attach(dev, xref));
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
@ -236,6 +237,7 @@ void
|
||||
openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv __unused)
|
||||
{
|
||||
struct openpic_softc *sc;
|
||||
uint32_t mask;
|
||||
|
||||
/* If we aren't directly connected to the CPU, this won't work */
|
||||
if (dev != root_pic)
|
||||
@ -247,7 +249,23 @@ openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv __unused)
|
||||
* XXX: openpic_write() is very special and just needs a 32 bits mask.
|
||||
* For the moment, just play dirty and get the first half word.
|
||||
*/
|
||||
openpic_write(sc, OPENPIC_IDEST(irq), cpumask.__bits[0] & 0xffffffff);
|
||||
mask = cpumask.__bits[0] & 0xffffffff;
|
||||
if (sc->sc_quirks & OPENPIC_QUIRK_SINGLE_BIND) {
|
||||
int i = mftb() % CPU_COUNT(&cpumask);
|
||||
int cpu, ncpu;
|
||||
|
||||
ncpu = 0;
|
||||
CPU_FOREACH(cpu) {
|
||||
if (!(mask & (1 << cpu)))
|
||||
continue;
|
||||
if (ncpu == i)
|
||||
break;
|
||||
ncpu++;
|
||||
}
|
||||
mask &= (1 << cpu);
|
||||
}
|
||||
|
||||
openpic_write(sc, OPENPIC_IDEST(irq), mask);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user