svn commit: r209486 - in head/sys/powerpc: aim include mpc85xx powermac powerpc

Nathan Whitehorn nwhitehorn at FreeBSD.org
Wed Jun 23 22:33:04 UTC 2010


Author: nwhitehorn
Date: Wed Jun 23 22:33:03 2010
New Revision: 209486
URL: http://svn.freebsd.org/changeset/base/209486

Log:
  Configure interrupts on SMP systems to be distributed among all online
  CPUs by default, and provide a functional version of BUS_BIND_INTR().
  While here, fix some potential concurrency problems in the interrupt
  handling code.

Modified:
  head/sys/powerpc/aim/nexus.c
  head/sys/powerpc/include/intr_machdep.h
  head/sys/powerpc/include/openpicvar.h
  head/sys/powerpc/mpc85xx/opic.c
  head/sys/powerpc/powermac/cpcht.c
  head/sys/powerpc/powermac/openpic_macio.c
  head/sys/powerpc/powerpc/intr_machdep.c
  head/sys/powerpc/powerpc/openpic.c
  head/sys/powerpc/powerpc/pic_if.m

Modified: head/sys/powerpc/aim/nexus.c
==============================================================================
--- head/sys/powerpc/aim/nexus.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/aim/nexus.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -119,6 +119,12 @@ static device_t nexus_add_child(device_t
 static void	nexus_probe_nomatch(device_t, device_t);
 static int	nexus_read_ivar(device_t, device_t, int, uintptr_t *);
 static int	nexus_write_ivar(device_t, device_t, int, uintptr_t);
+#ifdef SMP
+static int	nexus_bind_intr(device_t dev, device_t child,
+		    struct resource *irq, int cpu);
+#endif
+static int	nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+		    enum intr_polarity pol);
 static int	nexus_setup_intr(device_t, device_t, struct resource *, int,
 		    driver_filter_t *, driver_intr_t *, void *, void **);
 static int	nexus_teardown_intr(device_t, device_t, struct resource *,
@@ -162,6 +168,10 @@ static device_method_t nexus_methods[] =
 	DEVMETHOD(bus_write_ivar,	nexus_write_ivar),
 	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
 	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
+#ifdef SMP
+	DEVMETHOD(bus_bind_intr,	nexus_bind_intr),
+#endif
+	DEVMETHOD(bus_config_intr,	nexus_config_intr),
 	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
 	DEVMETHOD(bus_activate_resource,	nexus_activate_resource),
 	DEVMETHOD(bus_deactivate_resource,	nexus_deactivate_resource),
@@ -363,6 +373,23 @@ nexus_teardown_intr(device_t dev, device
 	return (powerpc_teardown_intr(cookie));
 }
 
+#ifdef SMP
+static int
+nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
+{
+
+        return (powerpc_bind_intr(rman_get_start(irq), cpu));
+}
+#endif
+        
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+
+        return (powerpc_config_intr(irq, trig, pol));
+}
+
 /*
  * Allocate resources at the behest of a child.  This only handles interrupts,
  * since I/O resources are handled by child busses.

Modified: head/sys/powerpc/include/intr_machdep.h
==============================================================================
--- head/sys/powerpc/include/intr_machdep.h	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/include/intr_machdep.h	Wed Jun 23 22:33:03 2010	(r209486)
@@ -56,6 +56,7 @@ int	powerpc_enable_intr(void);
 int	powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t,
 	    void *, enum intr_type, void **);
 int	powerpc_teardown_intr(void *);
+int	powerpc_bind_intr(u_int irq, u_char cpu);
 int	powerpc_config_intr(int, enum intr_trigger, enum intr_polarity);
 
 #endif /* _MACHINE_INTR_MACHDEP_H_ */

Modified: head/sys/powerpc/include/openpicvar.h
==============================================================================
--- head/sys/powerpc/include/openpicvar.h	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/include/openpicvar.h	Wed Jun 23 22:33:03 2010	(r209486)
@@ -57,6 +57,7 @@ int	openpic_attach(device_t);
 /*
  * PIC interface.
  */
+void	openpic_bind(device_t dev, u_int irq, cpumask_t cpumask);
 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);

Modified: head/sys/powerpc/mpc85xx/opic.c
==============================================================================
--- head/sys/powerpc/mpc85xx/opic.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/mpc85xx/opic.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -57,6 +57,7 @@ static device_method_t  openpic_ocpbus_m
 	DEVMETHOD(device_attach,	openpic_attach),
 
 	/* PIC interface */
+	DEVMETHOD(pic_bind,		openpic_bind),
 	DEVMETHOD(pic_config,		openpic_config),
 	DEVMETHOD(pic_dispatch,		openpic_dispatch),
 	DEVMETHOD(pic_enable,		openpic_enable),

Modified: head/sys/powerpc/powermac/cpcht.c
==============================================================================
--- head/sys/powerpc/powermac/cpcht.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/powermac/cpcht.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -751,6 +751,7 @@ static device_method_t  openpic_cpcht_me
 	DEVMETHOD(device_attach,	openpic_cpcht_attach),
 
 	/* PIC interface */
+	DEVMETHOD(pic_bind,		openpic_bind),
 	DEVMETHOD(pic_config,		openpic_cpcht_config),
 	DEVMETHOD(pic_dispatch,		openpic_dispatch),
 	DEVMETHOD(pic_enable,		openpic_cpcht_enable),

Modified: head/sys/powerpc/powermac/openpic_macio.c
==============================================================================
--- head/sys/powerpc/powermac/openpic_macio.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/powermac/openpic_macio.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -67,6 +67,7 @@ static device_method_t  openpic_macio_me
 	DEVMETHOD(device_attach,	openpic_attach),
 
 	/* PIC interface */
+	DEVMETHOD(pic_bind,		openpic_bind),
 	DEVMETHOD(pic_config,		openpic_config),
 	DEVMETHOD(pic_dispatch,		openpic_dispatch),
 	DEVMETHOD(pic_enable,		openpic_enable),

Modified: head/sys/powerpc/powerpc/intr_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/intr_machdep.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/powerpc/intr_machdep.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -73,6 +73,7 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/pcpu.h>
+#include <sys/smp.h>
 #include <sys/syslog.h>
 #include <sys/vmmeter.h>
 #include <sys/proc.h>
@@ -96,6 +97,7 @@ struct powerpc_intr {
 	device_t pic;
 	u_int	intline;
 	u_int	vector;
+	cpumask_t cpu;
 	enum intr_trigger trig;
 	enum intr_polarity pol;
 };
@@ -127,6 +129,23 @@ intr_init(void *dummy __unused)
 }
 SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
 
+#ifdef SMP
+static void
+smp_intr_init(void *dummy __unused)
+{
+	struct powerpc_intr *i;
+	int vector;
+
+	for (vector = 0; vector < nvectors; vector++) {
+		i = powerpc_intrs[vector];
+		if (i != NULL && i->pic == root_pic)
+			PIC_BIND(i->pic, i->intline, i->cpu);
+	}
+}
+
+SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
+#endif
+
 static void
 intrcnt_setname(const char *name, int index)
 {
@@ -150,11 +169,12 @@ intr_lookup(u_int irq)
 			return (i);
 		}
 	}
-	mtx_unlock(&intr_table_lock);
 
 	i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
-	if (i == NULL)
+	if (i == NULL) {
+		mtx_unlock(&intr_table_lock);
 		return (NULL);
+	}
 
 	i->event = NULL;
 	i->cntp = NULL;
@@ -164,7 +184,12 @@ intr_lookup(u_int irq)
 	i->pic = NULL;
 	i->vector = -1;
 
-	mtx_lock(&intr_table_lock);
+#ifdef SMP
+	i->cpu = all_cpus;
+#else
+	i->cpu = 1;
+#endif
+
 	for (vector = 0; vector < INTR_VECTORS && vector <= nvectors;
 	    vector++) {
 		iscan = powerpc_intrs[vector];
@@ -359,6 +384,9 @@ powerpc_setup_intr(const char *name, u_i
 		    i->pol != INTR_POLARITY_CONFORM))
 			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
 
+		if (!error && i->pic == root_pic)
+			PIC_BIND(i->pic, i->intline, i->cpu);
+
 		if (!error && enable)
 			PIC_ENABLE(i->pic, i->intline, i->vector);
 	}
@@ -372,6 +400,27 @@ powerpc_teardown_intr(void *cookie)
 	return (intr_event_remove_handler(cookie));
 }
 
+#ifdef SMP
+int
+powerpc_bind_intr(u_int irq, u_char cpu)
+{
+	struct powerpc_intr *i;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	if (cpu == NOCPU)
+		i->cpu = all_cpus;
+	else
+		i->cpu = 1 << cpu;
+
+	PIC_BIND(i->pic, i->intline, i->cpu);
+
+	return (intr_event_bind(i->event, cpu));
+}
+#endif
+
 int
 powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
 {

Modified: head/sys/powerpc/powerpc/openpic.c
==============================================================================
--- head/sys/powerpc/powerpc/openpic.c	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/powerpc/openpic.c	Wed Jun 23 22:33:03 2010	(r209486)
@@ -30,7 +30,9 @@
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
+#include <sys/proc.h>
 #include <sys/rman.h>
+#include <sys/sched.h>
 
 #include <machine/bus.h>
 #include <machine/intr.h>
@@ -72,11 +74,13 @@ openpic_set_priority(struct openpic_soft
 	u_int tpr;
 	uint32_t x;
 
+	sched_pin();
 	tpr = OPENPIC_PCPU_TPR(PCPU_GET(cpuid));
 	x = openpic_read(sc, tpr);
 	x &= ~OPENPIC_TPR_MASK;
 	x |= pri;
 	openpic_write(sc, tpr, x);
+	sched_unpin();
 }
 
 int
@@ -228,6 +232,19 @@ openpic_attach(device_t dev)
  */
 
 void
+openpic_bind(device_t dev, u_int irq, cpumask_t cpumask)
+{
+	struct openpic_softc *sc;
+
+	/* If we aren't directly connected to the CPU, this won't work */
+	if (dev != root_pic)
+		return;
+
+	sc = device_get_softc(dev);
+	openpic_write(sc, OPENPIC_IDEST(irq), cpumask);
+}
+
+void
 openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
     enum intr_polarity pol)
 {
@@ -313,8 +330,10 @@ openpic_ipi(device_t dev, u_int cpu)
 	struct openpic_softc *sc;
 
 	sc = device_get_softc(dev);
+	sched_pin();
 	openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
 	    1u << cpu);
+	sched_unpin();
 }
 
 void

Modified: head/sys/powerpc/powerpc/pic_if.m
==============================================================================
--- head/sys/powerpc/powerpc/pic_if.m	Wed Jun 23 22:25:52 2010	(r209485)
+++ head/sys/powerpc/powerpc/pic_if.m	Wed Jun 23 22:33:03 2010	(r209486)
@@ -32,6 +32,12 @@
 
 INTERFACE pic;
 
+METHOD void bind {
+	device_t	dev;
+	u_int		irq;
+	cpumask_t	cpumask;
+};
+
 METHOD void config {
 	device_t	dev;
 	u_int		irq;
@@ -73,3 +79,4 @@ METHOD void unmask {
 	device_t	dev;
 	u_int		irq;
 };
+


More information about the svn-src-all mailing list