Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Mar 2013 10:23:56 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r247881 - in stable/9/sys: amd64/acpica dev/acpica i386/acpica ia64/acpica
Message-ID:  <201303061023.r26ANurj072701@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Wed Mar  6 10:23:56 2013
New Revision: 247881
URL: http://svnweb.freebsd.org/changeset/base/247881

Log:
  MFC r233579,236403,236408: make interrupt flags management closer to head
  
  r233579: Restore interrupt state after executing AcpiEnterSleepState().
  r236403,236408: acpi_wakeup_machdep/acpi_sleep_machdep
  
  The merged changes are modified a bit to account for lots of missing
  acpi and acpica MFCs.
  For the same reason MFC to stable/8 is not practical.
  
  MFC slackers:	iwasaki, jkim

Modified:
  stable/9/sys/amd64/acpica/acpi_wakeup.c
  stable/9/sys/dev/acpica/acpi.c
  stable/9/sys/dev/acpica/acpivar.h
  stable/9/sys/i386/acpica/acpi_wakeup.c
  stable/9/sys/ia64/acpica/acpi_wakeup.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/amd64/acpica/acpi_wakeup.c	Wed Mar  6 09:53:38 2013	(r247880)
+++ stable/9/sys/amd64/acpica/acpi_wakeup.c	Wed Mar  6 10:23:56 2013	(r247881)
@@ -76,6 +76,10 @@ static struct pcb	**susppcbs;
 static void		**suspfpusave;
 #endif
 
+#ifdef SMP
+static cpuset_t		suspcpus;
+#endif
+
 int			acpi_restorecpu(uint64_t, vm_offset_t);
 
 static void		*acpi_alloc_wakeup_handler(void);
@@ -220,21 +224,14 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-#ifdef SMP
-	cpuset_t	wakeup_cpus;
-#endif
-	register_t	rf;
 	ACPI_STATUS	status;
-	int		ret;
-
-	ret = -1;
 
 	if (sc->acpi_wakeaddr == 0ul)
-		return (ret);
+		return (-1);	/* couldn't alloc wake memory */
 
 #ifdef SMP
-	wakeup_cpus = all_cpus;
-	CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus);
+	suspcpus = all_cpus;
+	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
 #endif
 
 	if (acpi_resume_beep != 0)
@@ -242,16 +239,15 @@ acpi_sleep_machdep(struct acpi_softc *sc
 
 	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
 
-	rf = intr_disable();
 	intr_suspend();
 
 	if (savectx(susppcbs[0])) {
 		ctx_fpusave(suspfpusave[0]);
 #ifdef SMP
-		if (!CPU_EMPTY(&wakeup_cpus) &&
-		    suspend_cpus(wakeup_cpus) == 0) {
+		if (!CPU_EMPTY(&suspcpus) &&
+		    suspend_cpus(suspcpus) == 0) {
 			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
-			goto out;
+			return (0);	/* couldn't sleep */
 		}
 #endif
 
@@ -276,41 +272,54 @@ acpi_sleep_machdep(struct acpi_softc *sc
 			device_printf(sc->acpi_dev,
 			    "AcpiEnterSleepState failed - %s\n",
 			    AcpiFormatException(status));
-			goto out;
+			return (0);	/* couldn't sleep */
 		}
 
 		for (;;)
 			ia32_pause();
-	} else {
-		pmap_init_pat();
-		load_cr3(susppcbs[0]->pcb_cr3);
-		initializecpu();
-		PCPU_SET(switchtime, 0);
-		PCPU_SET(switchticks, ticks);
-#ifdef SMP
-		if (!CPU_EMPTY(&wakeup_cpus))
-			acpi_wakeup_cpus(sc, &wakeup_cpus);
-#endif
-		ret = 0;
 	}
 
-out:
+	return (1);	/* wakeup successfully */
+}
+
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+
+	if (sleep_result == -1)
+		return (sleep_result);
+
+	if (intr_enabled == 0) {
+		/* Wakeup MD procedures in interrupt disabled context */
+		if (sleep_result == 1) {
+			pmap_init_pat();
+			load_cr3(susppcbs[0]->pcb_cr3);
+			initializecpu();
+			PCPU_SET(switchtime, 0);
+			PCPU_SET(switchticks, ticks);
 #ifdef SMP
-	if (!CPU_EMPTY(&wakeup_cpus))
-		restart_cpus(wakeup_cpus);
+			if (!CPU_EMPTY(&suspcpus))
+				acpi_wakeup_cpus(sc, &suspcpus);
 #endif
+		}
 
-	mca_resume();
-	intr_resume();
-	intr_restore(rf);
-
-	AcpiSetFirmwareWakingVector(0);
+#ifdef SMP
+		if (!CPU_EMPTY(&suspcpus))
+			restart_cpus(suspcpus);
+#endif
+		mca_resume();
+		intr_resume();
+	} else {
+		/* Wakeup MD procedures in interrupt enabled context */
+		AcpiSetFirmwareWakingVector(0);
 
-	if (ret == 0 && mem_range_softc.mr_op != NULL &&
-	    mem_range_softc.mr_op->reinit != NULL)
-		mem_range_softc.mr_op->reinit(&mem_range_softc);
+		if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
+		    mem_range_softc.mr_op->reinit != NULL)
+			mem_range_softc.mr_op->reinit(&mem_range_softc);
+	}
 
-	return (ret);
+	return (sleep_result);
 }
 
 static void *

Modified: stable/9/sys/dev/acpica/acpi.c
==============================================================================
--- stable/9/sys/dev/acpica/acpi.c	Wed Mar  6 09:53:38 2013	(r247880)
+++ stable/9/sys/dev/acpica/acpi.c	Wed Mar  6 10:23:56 2013	(r247881)
@@ -1960,6 +1960,7 @@ static void
 acpi_shutdown_final(void *arg, int howto)
 {
     struct acpi_softc *sc = (struct acpi_softc *)arg;
+    register_t intr;
     ACPI_STATUS status;
 
     /*
@@ -1975,13 +1976,15 @@ acpi_shutdown_final(void *arg, int howto
 	    return;
 	}
 	device_printf(sc->acpi_dev, "Powering system off\n");
-	ACPI_DISABLE_IRQS();
+	intr = intr_disable();
 	status = AcpiEnterSleepState(ACPI_STATE_S5);
-	if (ACPI_FAILURE(status))
+	if (ACPI_FAILURE(status)) {
+	    intr_restore(intr);
 	    device_printf(sc->acpi_dev, "power-off failed - %s\n",
 		AcpiFormatException(status));
-	else {
+	} else {
 	    DELAY(1000000);
+	    intr_restore(intr);
 	    device_printf(sc->acpi_dev, "power-off failed - timeout\n");
 	}
     } else if ((howto & RB_HALT) == 0 && sc->acpi_handle_reboot) {
@@ -2652,8 +2655,10 @@ enum acpi_sleep_state {
 static ACPI_STATUS
 acpi_EnterSleepState(struct acpi_softc *sc, int state)
 {
-    ACPI_STATUS	status;
+    register_t intr;
+    ACPI_STATUS status;
     enum acpi_sleep_state slp_state;
+    int sleep_result;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
@@ -2733,15 +2738,24 @@ acpi_EnterSleepState(struct acpi_softc *
     if (sc->acpi_sleep_delay > 0)
 	DELAY(sc->acpi_sleep_delay * 1000000);
 
+    intr = intr_disable();
     if (state != ACPI_STATE_S1) {
-	acpi_sleep_machdep(sc, state);
+	sleep_result = acpi_sleep_machdep(sc, state);
+	acpi_wakeup_machdep(sc, state, sleep_result, 0);
+	intr_restore(intr);
+
+	/* call acpi_wakeup_machdep() again with interrupt enabled */
+	acpi_wakeup_machdep(sc, state, sleep_result, 1);
+
+	if (sleep_result == -1)
+		goto backout;
 
 	/* Re-enable ACPI hardware on wakeup from sleep state 4. */
 	if (state == ACPI_STATE_S4)
 	    AcpiEnable();
     } else {
-	ACPI_DISABLE_IRQS();
 	status = AcpiEnterSleepState(state);
+	intr_restore(intr);
 	if (ACPI_FAILURE(status)) {
 	    device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
 			  AcpiFormatException(status));

Modified: stable/9/sys/dev/acpica/acpivar.h
==============================================================================
--- stable/9/sys/dev/acpica/acpivar.h	Wed Mar  6 09:53:38 2013	(r247880)
+++ stable/9/sys/dev/acpica/acpivar.h	Wed Mar  6 10:23:56 2013	(r247881)
@@ -434,6 +434,8 @@ int		acpi_disabled(char *subsys);
 int		acpi_machdep_init(device_t dev);
 void		acpi_install_wakeup_handler(struct acpi_softc *sc);
 int		acpi_sleep_machdep(struct acpi_softc *sc, int state);
+int		acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+		    int sleep_result, int intr_enabled);
 int		acpi_table_quirks(int *quirks);
 int		acpi_machdep_quirks(int *quirks);
 

Modified: stable/9/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/i386/acpica/acpi_wakeup.c	Wed Mar  6 09:53:38 2013	(r247880)
+++ stable/9/sys/i386/acpica/acpi_wakeup.c	Wed Mar  6 10:23:56 2013	(r247881)
@@ -74,6 +74,10 @@ extern struct pcb	**susppcbs;
 static struct pcb	**susppcbs;
 #endif
 
+#ifdef SMP
+static cpuset_t		suspcpus;
+#endif
+
 static void		*acpi_alloc_wakeup_handler(void);
 static void		acpi_stop_beep(void *);
 
@@ -212,22 +216,14 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-#ifdef SMP
-	cpuset_t	wakeup_cpus;
-#endif
-	register_t	cr3, rf;
 	ACPI_STATUS	status;
-	struct pmap	*pm;
-	int		ret;
-
-	ret = -1;
 
 	if (sc->acpi_wakeaddr == 0ul)
-		return (ret);
+		return (-1);	/* couldn't alloc wake memory */
 
 #ifdef SMP
-	wakeup_cpus = all_cpus;
-	CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus);
+	suspcpus = all_cpus;
+	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
 #endif
 
 	if (acpi_resume_beep != 0)
@@ -235,28 +231,14 @@ acpi_sleep_machdep(struct acpi_softc *sc
 
 	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
 
-	rf = intr_disable();
 	intr_suspend();
 
-	/*
-	 * Temporarily switch to the kernel pmap because it provides
-	 * an identity mapping (setup at boot) for the low physical
-	 * memory region containing the wakeup code.
-	 */
-	pm = kernel_pmap;
-	cr3 = rcr3();
-#ifdef PAE
-	load_cr3(vtophys(pm->pm_pdpt));
-#else
-	load_cr3(vtophys(pm->pm_pdir));
-#endif
-
 	if (suspendctx(susppcbs[0])) {
 #ifdef SMP
-		if (!CPU_EMPTY(&wakeup_cpus) &&
-		    suspend_cpus(wakeup_cpus) == 0) {
+		if (!CPU_EMPTY(&suspcpus) &&
+		    suspend_cpus(suspcpus) == 0) {
 			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
-			goto out;
+			return (0);	/* couldn't sleep */
 		}
 #endif
 
@@ -264,8 +246,6 @@ acpi_sleep_machdep(struct acpi_softc *sc
 		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
 
 		WAKECODE_FIXUP(wakeup_cr4, register_t, susppcbs[0]->pcb_cr4);
-		WAKECODE_FIXUP(wakeup_cr3, register_t, susppcbs[0]->pcb_cr3);
-
 		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
 
 		/* Call ACPICA to enter the desired sleep state */
@@ -278,41 +258,54 @@ acpi_sleep_machdep(struct acpi_softc *sc
 			device_printf(sc->acpi_dev,
 			    "AcpiEnterSleepState failed - %s\n",
 			    AcpiFormatException(status));
-			goto out;
+			return (0);	/* couldn't sleep */
 		}
 
 		for (;;)
 			ia32_pause();
-	} else {
-		pmap_init_pat();
-		initializecpu();
-		PCPU_SET(switchtime, 0);
-		PCPU_SET(switchticks, ticks);
+	}
+
+	return (1);	/* wakeup successfully */
+}
+
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+
+	if (sleep_result == -1)
+		return (sleep_result);
+
+	if (intr_enabled == 0) {
+		/* Wakeup MD procedures in interrupt disabled context */
+		if (sleep_result == 1) {
+			pmap_init_pat();
+			load_cr3(susppcbs[0]->pcb_cr3);
+			initializecpu();
+			PCPU_SET(switchtime, 0);
+			PCPU_SET(switchticks, ticks);
 #ifdef SMP
-		if (!CPU_EMPTY(&wakeup_cpus))
-			acpi_wakeup_cpus(sc, &wakeup_cpus);
+			if (!CPU_EMPTY(&suspcpus))
+				acpi_wakeup_cpus(sc, &suspcpus);
 #endif
-		ret = 0;
-	}
+		}
 
-out:
 #ifdef SMP
-	if (!CPU_EMPTY(&wakeup_cpus))
-		restart_cpus(wakeup_cpus);
+		if (!CPU_EMPTY(&suspcpus))
+			restart_cpus(suspcpus);
 #endif
+		mca_resume();
+		intr_resume();
+	} else {
+		/* Wakeup MD procedures in interrupt enabled context */
+		AcpiSetFirmwareWakingVector(0);
 
-	load_cr3(cr3);
-	mca_resume();
-	intr_resume();
-	intr_restore(rf);
-
-	AcpiSetFirmwareWakingVector(0);
-
-	if (ret == 0 && mem_range_softc.mr_op != NULL &&
-	    mem_range_softc.mr_op->reinit != NULL)
-		mem_range_softc.mr_op->reinit(&mem_range_softc);
+		if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
+		    mem_range_softc.mr_op->reinit != NULL)
+			mem_range_softc.mr_op->reinit(&mem_range_softc);
+	}
 
-	return (ret);
+	return (sleep_result);
 }
 
 static void *
@@ -373,6 +366,16 @@ acpi_install_wakeup_handler(struct acpi_
 
 	/* Save pointers to some global data. */
 	WAKECODE_FIXUP(wakeup_ret, void *, resumectx);
+	/*
+	 * Temporarily switch to the kernel pmap because it provides
+	 * an identity mapping (setup at boot) for the low physical
+	 * memory region containing the wakeup code.
+	 */
+#ifdef PAE
+	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdpt));
+#else
+	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdir));
+#endif
 
 	if (bootverbose)
 		device_printf(sc->acpi_dev, "wakeup code va %#x pa %#jx\n",

Modified: stable/9/sys/ia64/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/ia64/acpica/acpi_wakeup.c	Wed Mar  6 09:53:38 2013	(r247880)
+++ stable/9/sys/ia64/acpica/acpi_wakeup.c	Wed Mar  6 10:23:56 2013	(r247881)
@@ -39,6 +39,13 @@ acpi_sleep_machdep(struct acpi_softc *sc
 	return (0);
 }
 
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+	return (0);
+}
+
 void
 acpi_install_wakeup_handler(struct acpi_softc *sc)
 {



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