ACPI throttling changes
Nate Lawson
nate at root.org
Tue Dec 9 17:57:57 PST 2003
I'm working on a shared CPU frequency control driver. One step is to
remove some of the autonomy of the throttling portion of acpi_cpu.
Please test this patch if you have a machine which supports throttling.
With this patch, throttling can be changed by doing:
sysctl hw.acpi.cpu.current_speed=X
where X is some number between 1 and hw.acpi.cpu.max_speed. It is no
longer driven by AC line transitions. Run a CPU benchmark like this one
to make sure the throttling transition still works with this patch.
dd if=/dev/zero bs=1m count=500 | md5
This is part of a larger work. Don't worry, it won't be committed until
general CPU frequency control is done so no loss of functionality will be
committed.
-Nate
Index: sys/dev/acpica/acpi_cpu.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_cpu.c,v
retrieving revision 1.24
diff -u -r1.24 acpi_cpu.c
--- sys/dev/acpica/acpi_cpu.c 9 Dec 2003 03:01:54 -0000 1.24
+++ sys/dev/acpica/acpi_cpu.c 10 Dec 2003 01:40:29 -0000
@@ -135,8 +135,6 @@
/* Values for sysctl. */
static uint32_t cpu_current_state;
-static uint32_t cpu_performance_state;
-static uint32_t cpu_economy_state;
static uint32_t cpu_max_state;
static int cpu_cx_lowest;
static char cpu_cx_supported[64];
@@ -165,7 +163,6 @@
static void acpi_pm_ticksub(uint32_t *end, const uint32_t *start);
static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context);
static int acpi_cpu_quirks(struct acpi_cpu_softc *sc);
-static void acpi_cpu_power_profile(void *arg);
static int acpi_cpu_throttle_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_cpu_history_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS);
@@ -616,10 +613,6 @@
/* Get set of CPU devices */
devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);
- /* Register performance profile change handler */
- EVENTHANDLER_REGISTER(power_profile_change, acpi_cpu_power_profile,
- NULL, 0);
-
/*
* Make sure all the processors' Cx counts match. We should probably
* also check the contents of each. However, no known systems have
@@ -647,56 +640,30 @@
static void
acpi_cpu_startup_throttling()
{
- int cpu_temp_speed;
ACPI_LOCK_DECL;
/* Initialise throttling states */
cpu_max_state = CPU_MAX_SPEED;
- cpu_performance_state = cpu_max_state;
- cpu_economy_state = cpu_performance_state / 2;
-
- /* 0 is 'reserved' */
- if (cpu_economy_state == 0)
- cpu_economy_state++;
- if (TUNABLE_INT_FETCH("hw.acpi.cpu.performance_speed", &cpu_temp_speed) &&
- cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
-
- cpu_performance_state = cpu_temp_speed;
- }
- if (TUNABLE_INT_FETCH("hw.acpi.cpu.economy_speed", &cpu_temp_speed) &&
- cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
-
- cpu_economy_state = cpu_temp_speed;
- }
+ cpu_current_state = CPU_MAX_SPEED;
SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
OID_AUTO, "max_speed", CTLFLAG_RD,
&cpu_max_state, 0, "maximum CPU speed");
- SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
- SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
- OID_AUTO, "current_speed", CTLFLAG_RD,
- &cpu_current_state, 0, "current CPU speed");
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
- OID_AUTO, "performance_speed",
- CTLTYPE_INT | CTLFLAG_RW, &cpu_performance_state,
- 0, acpi_cpu_throttle_sysctl, "I", "");
- SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
- SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
- OID_AUTO, "economy_speed",
- CTLTYPE_INT | CTLFLAG_RW, &cpu_economy_state,
- 0, acpi_cpu_throttle_sysctl, "I", "");
+ OID_AUTO, "current_speed",
+ CTLTYPE_INT | CTLFLAG_RW, &cpu_current_state,
+ 0, acpi_cpu_throttle_sysctl, "I", "current CPU speed");
/* If ACPI 2.0+, signal platform that we are taking over throttling. */
- if (cpu_pstate_cnt != 0) {
- ACPI_LOCK;
+ ACPI_LOCK;
+ if (cpu_pstate_cnt != 0)
AcpiOsWritePort(cpu_smi_cmd, cpu_pstate_cnt, 8);
- ACPI_UNLOCK;
- }
- /* Set initial speed */
- acpi_cpu_power_profile(NULL);
+ /* Set initial speed to maximum. */
+ acpi_cpu_throttle_set(cpu_max_state);
+ ACPI_UNLOCK;
printf("acpi_cpu: throttling enabled, %d steps (100%% to %d.%d%%), "
"currently %d.%d%%\n", CPU_MAX_SPEED, CPU_SPEED_PRINTABLE(1),
@@ -1026,54 +993,14 @@
return (0);
}
-/*
- * Power profile change hook.
- *
- * Uses the ACPI lock to avoid reentrancy.
- */
-static void
-acpi_cpu_power_profile(void *arg)
-{
- int state;
- uint32_t new;
- ACPI_LOCK_DECL;
-
- state = power_profile_get_state();
- if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
- return;
-
- ACPI_LOCK;
-
- switch (state) {
- case POWER_PROFILE_PERFORMANCE:
- new = cpu_performance_state;
- break;
- case POWER_PROFILE_ECONOMY:
- new = cpu_economy_state;
- break;
- default:
- new = cpu_current_state;
- break;
- }
-
- if (cpu_current_state != new)
- acpi_cpu_throttle_set(new);
-
- ACPI_UNLOCK;
-}
-
-/*
- * Handle changes in the performance/ecomony CPU settings.
- *
- * Does not need the ACPI lock (although setting *argp should
- * probably be atomic).
- */
+/* Handle changes in the CPU throttling setting. */
static int
acpi_cpu_throttle_sysctl(SYSCTL_HANDLER_ARGS)
{
uint32_t *argp;
uint32_t arg;
int error;
+ ACPI_LOCK_DECL;
argp = (uint32_t *)oidp->oid_arg1;
arg = *argp;
@@ -1085,9 +1012,13 @@
if (arg < 1 || arg > cpu_max_state)
return (EINVAL);
- /* Set new value and possibly switch */
- *argp = arg;
- acpi_cpu_power_profile(NULL);
+ /* If throttling changed, notify the BIOS of the new rate. */
+ ACPI_LOCK;
+ if (*argp != arg) {
+ *argp = arg;
+ acpi_cpu_throttle_set(arg);
+ }
+ ACPI_UNLOCK;
return (0);
}
More information about the freebsd-current
mailing list