Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Feb 2019 03:52:15 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r343824 - in head/sys/powerpc: include ofw powerpc
Message-ID:  <201902060352.x163qFMA058193@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Wed Feb  6 03:52:14 2019
New Revision: 343824
URL: https://svnweb.freebsd.org/changeset/base/343824

Log:
  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

Modified:
  head/sys/powerpc/include/openpicvar.h
  head/sys/powerpc/ofw/openpic_ofw.c
  head/sys/powerpc/powerpc/openpic.c

Modified: head/sys/powerpc/include/openpicvar.h
==============================================================================
--- head/sys/powerpc/include/openpicvar.h	Wed Feb  6 02:35:56 2019	(r343823)
+++ head/sys/powerpc/include/openpicvar.h	Wed Feb  6 03:52:14 2019	(r343824)
@@ -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;

Modified: head/sys/powerpc/ofw/openpic_ofw.c
==============================================================================
--- head/sys/powerpc/ofw/openpic_ofw.c	Wed Feb  6 02:35:56 2019	(r343823)
+++ head/sys/powerpc/ofw/openpic_ofw.c	Wed Feb  6 03:52:14 2019	(r343824)
@@ -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));
 }

Modified: head/sys/powerpc/powerpc/openpic.c
==============================================================================
--- head/sys/powerpc/powerpc/openpic.c	Wed Feb  6 02:35:56 2019	(r343823)
+++ head/sys/powerpc/powerpc/openpic.c	Wed Feb  6 03:52:14 2019	(r343824)
@@ -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
 	 * 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902060352.x163qFMA058193>