Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Jun 2012 15:26:33 +0000 (UTC)
From:      Mitsuru IWASAKI <iwasaki@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r236403 - in head/sys: amd64/acpica dev/acpica i386/acpica ia64/acpica
Message-ID:  <201206011526.q51FQX8h027075@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iwasaki
Date: Fri Jun  1 15:26:32 2012
New Revision: 236403
URL: http://svn.freebsd.org/changeset/base/236403

Log:
  Call AcpiLeaveSleepStatePrep() in interrupt disabled context
  (described in ACPICA source code).
  
  - Move intr_disable() and intr_restore() from acpi_wakeup.c to acpi.c
    and call AcpiLeaveSleepStatePrep() in interrupt disabled context.
  - Add acpi_wakeup_machdep() to execute wakeup MD procedures and call
    it twice in interrupt disabled/enabled context (ia64 version is
    just dummy).
  - Rename wakeup_cpus variable in acpi_sleep_machdep() to suspcpus in
    order to be shared by acpi_sleep_machdep() and acpi_wakeup_machdep().
  - Move identity mapping related code to acpi_install_wakeup_handler()
    (i386 version) for preparation of x86/acpica/acpi_wakeup.c
    (MFC candidate).
  
  Reviewed by:	jkim@
  MFC after:	2 days

Modified:
  head/sys/amd64/acpica/acpi_wakeup.c
  head/sys/dev/acpica/acpi.c
  head/sys/dev/acpica/acpivar.h
  head/sys/i386/acpica/acpi_wakeup.c
  head/sys/ia64/acpica/acpi_wakeup.c

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c	Fri Jun  1 15:02:23 2012	(r236402)
+++ head/sys/amd64/acpica/acpi_wakeup.c	Fri Jun  1 15:26:32 2012	(r236403)
@@ -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: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c	Fri Jun  1 15:02:23 2012	(r236402)
+++ head/sys/dev/acpica/acpi.c	Fri Jun  1 15:26:32 2012	(r236403)
@@ -2666,6 +2666,7 @@ acpi_EnterSleepState(struct acpi_softc *
     register_t intr;
     ACPI_STATUS status;
     enum acpi_sleep_state slp_state;
+    int sleep_result;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
@@ -2746,7 +2747,16 @@ acpi_EnterSleepState(struct acpi_softc *
 	DELAY(sc->acpi_sleep_delay * 1000000);
 
     if (state != ACPI_STATE_S1) {
-	if (acpi_sleep_machdep(sc, state))
+	intr = intr_disable();
+	sleep_result = acpi_sleep_machdep(sc, state);
+	acpi_wakeup_machdep(sc, state, sleep_result, 0);
+	AcpiLeaveSleepStatePrep(state, acpi_sleep_flags);
+	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. */
@@ -2775,10 +2785,8 @@ backout:
     }
     if (slp_state >= ACPI_SS_DEV_SUSPEND)
 	DEVICE_RESUME(root_bus);
-    if (slp_state >= ACPI_SS_SLP_PREP) {
-	AcpiLeaveSleepStatePrep(state, acpi_sleep_flags);
+    if (slp_state >= ACPI_SS_SLP_PREP)
 	AcpiLeaveSleepState(state);
-    }
     if (slp_state >= ACPI_SS_SLEPT) {
 	acpi_resync_clock(sc);
 	acpi_enable_fixed_events(sc);

Modified: head/sys/dev/acpica/acpivar.h
==============================================================================
--- head/sys/dev/acpica/acpivar.h	Fri Jun  1 15:02:23 2012	(r236402)
+++ head/sys/dev/acpica/acpivar.h	Fri Jun  1 15:26:32 2012	(r236403)
@@ -439,6 +439,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: head/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/i386/acpica/acpi_wakeup.c	Fri Jun  1 15:02:23 2012	(r236402)
+++ head/sys/i386/acpica/acpi_wakeup.c	Fri Jun  1 15:26:32 2012	(r236403)
@@ -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: head/sys/ia64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/ia64/acpica/acpi_wakeup.c	Fri Jun  1 15:02:23 2012	(r236402)
+++ head/sys/ia64/acpica/acpi_wakeup.c	Fri Jun  1 15:26:32 2012	(r236403)
@@ -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?201206011526.q51FQX8h027075>