diff options
author | njl <njl@FreeBSD.org> | 2004-03-19 07:05:01 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-03-19 07:05:01 +0000 |
commit | 00144b17be394da86d31254bf01ecb23e366988b (patch) | |
tree | 68c529b021df291a706bfaa2e63792e232ff81d3 /sys | |
parent | 1ed00c0897a65b90d20e9a1c4c53a69043965967 (diff) | |
download | FreeBSD-src-00144b17be394da86d31254bf01ecb23e366988b.zip FreeBSD-src-00144b17be394da86d31254bf01ecb23e366988b.tar.gz |
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/acpica/acpi.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 41b2cdf..2e3d3d1 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; |