aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
authorNate Lawson <njl@FreeBSD.org>2004-03-19 07:05:01 +0000
committerNate Lawson <njl@FreeBSD.org>2004-03-19 07:05:01 +0000
commiteeb3a05f9a9c93cddef556c33ed91b037c95eecd (patch)
tree68c529b021df291a706bfaa2e63792e232ff81d3 /sys/dev/acpica/acpi.c
parent4de762365a9b9a7abf2c4f8634a18d2c79e9fb8d (diff)
downloadsrc-eeb3a05f9a9c93cddef556c33ed91b037c95eecd.tar.gz
src-eeb3a05f9a9c93cddef556c33ed91b037c95eecd.zip
Move the poweroff handler to a separate function. Make sure it is run
on the boot processor (cpuid == 0). Some chipsets do not power off the system if the shutdown handler runs on an AP.
Notes
Notes: svn path=/head/; revision=127193
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 41b2cdf738fe..2e3d3d1e029b 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -44,6 +44,7 @@
#include <sys/linker.h>
#include <sys/power.h>
#include <sys/sbuf.h>
+#include <sys/smp.h>
#include <machine/clock.h>
#include <machine/resource.h>
@@ -132,6 +133,7 @@ static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level,
void *context, void **status);
static void acpi_shutdown_pre_sync(void *arg, int howto);
static void acpi_shutdown_final(void *arg, int howto);
+static void acpi_shutdown_poweroff(void *arg);
static void acpi_enable_fixed_events(struct acpi_softc *sc);
static void acpi_system_eventhandler_sleep(void *arg, int state);
static void acpi_system_eventhandler_wakeup(void *arg, int state);
@@ -1177,26 +1179,17 @@ acpi_shutdown_pre_sync(void *arg, int howto)
static void
acpi_shutdown_final(void *arg, int howto)
{
- ACPI_STATUS status;
ACPI_ASSERTLOCK;
+ /*
+ * If powering off, run the actual shutdown code on each processor.
+ * It will only perform the shutdown on the BSP. Some chipsets do
+ * not power off the system correctly if called from an AP.
+ */
if ((howto & RB_POWEROFF) != 0) {
printf("Powering system off using ACPI\n");
- status = AcpiEnterSleepStatePrep(acpi_off_state);
- if (ACPI_FAILURE(status)) {
- printf("AcpiEnterSleepStatePrep failed - %s\n",
- AcpiFormatException(status));
- return;
- }
- ACPI_DISABLE_IRQS();
- status = AcpiEnterSleepState(acpi_off_state);
- if (ACPI_FAILURE(status)) {
- printf("ACPI power-off failed - %s\n", AcpiFormatException(status));
- } else {
- DELAY(1000000);
- printf("ACPI power-off failed - timeout\n");
- }
+ smp_rendezvous(NULL, acpi_shutdown_poweroff, NULL, NULL);
} else {
printf("Shutting down ACPI\n");
AcpiTerminate();
@@ -1204,6 +1197,33 @@ acpi_shutdown_final(void *arg, int howto)
}
static void
+acpi_shutdown_poweroff(void *arg)
+{
+ ACPI_STATUS status;
+
+ ACPI_ASSERTLOCK;
+
+ /* Only attempt to power off if this is the BSP (cpuid 0). */
+ if (PCPU_GET(cpuid) != 0)
+ return;
+
+ status = AcpiEnterSleepStatePrep(acpi_off_state);
+ if (ACPI_FAILURE(status)) {
+ printf("AcpiEnterSleepStatePrep failed - %s\n",
+ AcpiFormatException(status));
+ return;
+ }
+ ACPI_DISABLE_IRQS();
+ status = AcpiEnterSleepState(acpi_off_state);
+ if (ACPI_FAILURE(status)) {
+ printf("ACPI power-off failed - %s\n", AcpiFormatException(status));
+ } else {
+ DELAY(1000000);
+ printf("ACPI power-off failed - timeout\n");
+ }
+}
+
+static void
acpi_enable_fixed_events(struct acpi_softc *sc)
{
static int first_time = 1;