Machine don't necessarily come out of suspend with CPUs running at the speed they suspended with. So we might end up in the situation where apmd(8) thinks we're running at maximum speed while the CPU is clocked down to its lowest speed, and that situation perpetuates because apmd(9) doesn't adjust hw.setperf. Easiest way out is to just call cpu_setperf() is the resume path with the current hw.setperf setting. The apm(4) resume code already does this. The diff below makes acpi(4) do the same thing.
I put the call fairly late into the resume path. Doing it earlier (before bufq_restart() like the apm(4) code does) broke resume on my x220. Perhaps we should adjust apm(4) to do this call later as well. ok? Index: acpi.c =================================================================== RCS file: /home/cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.248 diff -u -p -r1.248 acpi.c --- acpi.c 6 Dec 2013 21:03:02 -0000 1.248 +++ acpi.c 13 Dec 2013 23:10:10 -0000 @@ -30,6 +30,7 @@ #include <sys/workq.h> #include <sys/sched.h> #include <sys/reboot.h> +#include <sys/sysctl.h> #ifdef HIBERNATE #include <sys/hibernate.h> @@ -2084,6 +2085,7 @@ acpi_indicator(struct acpi_softc *sc, in int acpi_sleep_state(struct acpi_softc *sc, int state) { + extern int perflevel; int error = ENXIO; int s; @@ -2183,6 +2185,10 @@ fail_quiesce: #if NWSDISPLAY > 0 wsdisplay_resume(); #endif /* NWSDISPLAY > 0 */ + + /* Restore hw.setperf */ + if (cpu_setperf != NULL) + cpu_setperf(perflevel); acpi_record_event(sc, APM_NORMAL_RESUME); acpi_indicator(sc, ACPI_SST_WORKING);