From owner-freebsd-current@FreeBSD.ORG Tue Dec 9 17:57:57 2003 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BE96C16A4CE for ; Tue, 9 Dec 2003 17:57:57 -0800 (PST) Received: from rootlabs.com (root.org [67.118.192.226]) by mx1.FreeBSD.org (Postfix) with SMTP id 2A96F43D09 for ; Tue, 9 Dec 2003 17:57:52 -0800 (PST) (envelope-from nate@rootlabs.com) Received: (qmail 44059 invoked by uid 1000); 10 Dec 2003 01:57:53 -0000 Date: Tue, 9 Dec 2003 17:57:53 -0800 (PST) From: Nate Lawson To: current@freebsd.org Message-ID: <20031209175230.I44055@root.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: acpi-jp@jp.freebsd.org Subject: ACPI throttling changes X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Dec 2003 01:57:57 -0000 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); }