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 _at__at_ -135,8 +135,6 _at__at_ /* 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]; _at__at_ -165,7 +163,6 _at__at_ 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); _at__at_ -616,10 +613,6 _at__at_ /* 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 _at__at_ -647,56 +640,30 _at__at_ 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), _at__at_ -1026,54 +993,14 _at__at_ 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; _at__at_ -1085,9 +1012,13 _at__at_ 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); }Received on Tue Dec 09 2003 - 16:57:57 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:33 UTC