svn commit: r247600 - in head/sys: conf sparc64/pci

Marius Strobl marius at FreeBSD.org
Sat Mar 2 00:37:32 UTC 2013


Author: marius
Date: Sat Mar  2 00:37:31 2013
New Revision: 247600
URL: http://svnweb.freebsd.org/changeset/base/247600

Log:
  - While Netra X1 generally show no ill effects when registering a power
    fail interrupt handler, there seems to be either a broken batch of them
    or a tendency to develop a defect which causes this interrupt to fire
    inadvertedly. Given that apart from this problem these machines work
    just fine, add a tunable allowing the setup of the power fail interrupt
    to be disabled.
    While at it, remove the DEBUGGER_ON_POWERFAIL compile time option and
    make that behavior also selectable via the newly added tunable.
  - Apparently, it's no longer a problem to call shutdown_nice(9) from within
    an interrupt filter (some other drivers in the tree do the same). So
    change the power fail interrupt from an handler in order to simplify the
    code and get rid of a !INTR_MPSAFE handler.
  - Use NULL instead of 0 for pointers.
  
  MFC after:	1 week

Modified:
  head/sys/conf/options.sparc64
  head/sys/sparc64/pci/psycho.c

Modified: head/sys/conf/options.sparc64
==============================================================================
--- head/sys/conf/options.sparc64	Sat Mar  2 00:21:29 2013	(r247599)
+++ head/sys/conf/options.sparc64	Sat Mar  2 00:37:31 2013	(r247600)
@@ -23,7 +23,6 @@ PSM_DEBUG		opt_psm.h
 PSM_HOOKRESUME		opt_psm.h
 PSM_RESETAFTERSUSPEND	opt_psm.h
 
-DEBUGGER_ON_POWERFAIL	opt_psycho.h
 PSYCHO_DEBUG		opt_psycho.h
 
 SCHIZO_DEBUG		opt_schizo.h

Modified: head/sys/sparc64/pci/psycho.c
==============================================================================
--- head/sys/sparc64/pci/psycho.c	Sat Mar  2 00:21:29 2013	(r247599)
+++ head/sys/sparc64/pci/psycho.c	Sat Mar  2 00:37:31 2013	(r247600)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/pcpu.h>
 #include <sys/reboot.h>
 #include <sys/rman.h>
+#include <sys/sysctl.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_pci.h>
@@ -80,7 +81,7 @@ static const struct psycho_desc *psycho_
     const char *);
 static const struct psycho_desc *psycho_get_desc(device_t);
 static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
-    driver_filter_t, driver_intr_t);
+    driver_filter_t);
 static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
     bus_addr_t *, u_long *);
 static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map,
@@ -94,8 +95,9 @@ static void psycho_intr_clear(void *);
 static driver_filter_t psycho_ue;
 static driver_filter_t psycho_ce;
 static driver_filter_t psycho_pci_bus;
-static driver_filter_t psycho_powerfail;
-static driver_intr_t psycho_overtemp;
+static driver_filter_t psycho_powerdebug;
+static driver_filter_t psycho_powerdown;
+static driver_filter_t psycho_overtemp;
 #ifdef PSYCHO_MAP_WAKEUP
 static driver_filter_t psycho_wakeup;
 #endif
@@ -159,9 +161,16 @@ static devclass_t psycho_devclass;
 
 DEFINE_CLASS_0(pcib, psycho_driver, psycho_methods,
     sizeof(struct psycho_softc));
-EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0,
+EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, NULL, NULL,
     BUS_PASS_BUS);
 
+static SYSCTL_NODE(_hw, OID_AUTO, psycho, CTLFLAG_RD, 0, "psycho parameters");
+
+static u_int psycho_powerfail = 1;
+TUNABLE_INT("hw.psycho.powerfail", &psycho_powerfail);
+SYSCTL_UINT(_hw_psycho, OID_AUTO, powerfail, CTLFLAG_RDTUN, &psycho_powerfail,
+    0, "powerfail action (0: none, 1: shutdown (default), 2: debugger)");
+
 static SLIST_HEAD(, psycho_softc) psycho_softcs =
     SLIST_HEAD_INITIALIZER(psycho_softcs);
 
@@ -610,15 +619,20 @@ psycho_attach(device_t dev)
 		 * XXX Not all controllers have these, but installing them
 		 * is better than trying to sort through this mess.
 		 */
-		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL);
-		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL);
-#ifdef DEBUGGER_ON_POWERFAIL
-		psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, psycho_powerfail,
-		    NULL);
-#else
-		psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL,
-		    (driver_intr_t *)psycho_powerfail);
-#endif
+		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue);
+		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce);
+		switch (psycho_powerfail) {
+		case 0:
+			break;
+		case 2:
+			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
+			    psycho_powerdebug);
+			break;
+		default:
+			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
+			    psycho_powerdown);
+			break;
+		}
 		if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
 			/*
 			 * Hummingbirds/Sabres do not have the following two
@@ -630,14 +644,14 @@ psycho_attach(device_t dev)
 			 * over-temperature interrupt.
 			 */
 			psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP,
-			    NULL, psycho_overtemp);
+			    psycho_overtemp);
 #ifdef PSYCHO_MAP_WAKEUP
 			/*
 			 * psycho_wakeup() doesn't do anything useful right
 			 * now.
 			 */
 			psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP,
-			    psycho_wakeup, NULL);
+			    psycho_wakeup);
 #endif /* PSYCHO_MAP_WAKEUP */
 		}
 	}
@@ -647,7 +661,7 @@ psycho_attach(device_t dev)
 	 * interrupt but they are also only used for PCI bus A.
 	 */
 	psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP :
-	    PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL);
+	    PSR_PCIBERR_INT_MAP, psycho_pci_bus);
 
 	/*
 	 * Set the latency timer register as this isn't always done by the
@@ -687,7 +701,7 @@ psycho_attach(device_t dev)
 
 static void
 psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
-    driver_filter_t filt, driver_intr_t intr)
+    driver_filter_t handler)
 {
 	u_long vec;
 	int rid;
@@ -708,7 +722,7 @@ psycho_set_intr(struct psycho_softc *sc,
 	    INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
 	    intr_vectors[vec].iv_ic != &psycho_ic ||
 	    bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
-	    INTR_TYPE_MISC | INTR_BRIDGE, filt, intr, sc,
+	    INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, sc,
 	    &sc->sc_ihand[index]) != 0)
 		panic("%s: failed to set up interrupt %d", __func__, index);
 }
@@ -837,13 +851,16 @@ psycho_pci_bus(void *arg)
 }
 
 static int
-psycho_powerfail(void *arg)
+psycho_powerdebug(void *arg __unused)
 {
-#ifdef DEBUGGER_ON_POWERFAIL
-	struct psycho_softc *sc = arg;
 
 	kdb_enter(KDB_WHY_POWERFAIL, "powerfail");
-#else
+	return (FILTER_HANDLED);
+}
+
+static int
+psycho_powerdown(void *arg __unused)
+{
 	static int shutdown;
 
 	/* As the interrupt is cleared we may be called multiple times. */
@@ -851,22 +868,22 @@ psycho_powerfail(void *arg)
 		return (FILTER_HANDLED);
 	shutdown++;
 	printf("Power Failure Detected: Shutting down NOW.\n");
-	shutdown_nice(0);
-#endif
+	shutdown_nice(RB_POWEROFF);
 	return (FILTER_HANDLED);
 }
 
-static void
-psycho_overtemp(void *arg)
+static int
+psycho_overtemp(void *arg __unused)
 {
 	static int shutdown;
 
 	/* As the interrupt is cleared we may be called multiple times. */
 	if (shutdown != 0)
-		return;
+		return (FILTER_HANDLED);
 	shutdown++;
 	printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n");
 	shutdown_nice(RB_POWEROFF);
+	return (FILTER_HANDLED);
 }
 
 #ifdef PSYCHO_MAP_WAKEUP


More information about the svn-src-all mailing list