patch-2.4.6 linux/drivers/acpi/ospm/processor/prperf.c

Next file: linux/drivers/acpi/ospm/processor/prpower.c
Previous file: linux/drivers/acpi/ospm/processor/pr_osl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/prperf.c linux/drivers/acpi/ospm/processor/prperf.c
@@ -0,0 +1,423 @@
+/*****************************************************************************
+ *
+ * Module Name: prperf.c
+ *              $Revision: 16 $
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 Andrew Grover
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * TBD: 1. Support ACPI 2.0 processor performance states (not just throttling).
+ *      2. Fully implement thermal -vs- power management limit control.
+ */
+
+
+#include <acpi.h>
+#include <bm.h>
+#include "pr.h"
+
+#define _COMPONENT		ACPI_PROCESSOR
+	MODULE_NAME		("prperf")
+
+
+/****************************************************************************
+ *                                  Globals
+ ****************************************************************************/
+
+extern FADT_DESCRIPTOR_REV2	acpi_fadt;
+const u32			POWER_OF_2[] = {1,2,4,8,16,32,64,128,256,512};
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_get_frequency
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+pr_perf_get_frequency (
+	PR_CONTEXT		*processor,
+	u32			*frequency) {
+	ACPI_STATUS		status = AE_OK;
+
+	if (!processor || !frequency) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	/* TBD: Generic method to calculate processor frequency. */
+
+	return(status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_get_state
+ *
+ * PARAMETERS:
+ *
+ * RETURN:	
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+/* TBD:	Include support for _real_ performance states (not just throttling). */
+
+ACPI_STATUS
+pr_perf_get_state (
+	PR_CONTEXT              *processor,
+	u32                     *state)
+{
+	u32                     pblk_value = 0;
+	u32                     duty_mask = 0;
+	u32                     duty_cycle = 0;
+
+	if (!processor || !state) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	if (processor->performance.state_count == 1) {
+		*state = 0;
+		return(AE_OK);
+	}
+
+	pblk_value = acpi_os_in32(processor->pblk.address);
+
+	/*
+	 * Throttling Enabled?
+	 * -------------------
+	 * If so, calculate the current throttling state, otherwise return
+	 * '100% performance' (state 0).
+	 */
+	if (pblk_value & 0x00000010) {
+
+		duty_mask = processor->performance.state_count - 1;
+		duty_mask <<= acpi_fadt.duty_offset;
+
+		duty_cycle = pblk_value & duty_mask;
+		duty_cycle >>= acpi_fadt.duty_offset;
+
+		if (duty_cycle == 0) {
+			*state = 0;
+		}
+		else {
+			*state = processor->performance.state_count -
+				duty_cycle;
+		}
+	}
+	else {
+		*state = 0;
+	}
+
+	return(AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_set_state
+ *
+ * PARAMETERS:
+ *
+ * RETURN:      AE_OK
+ *              AE_BAD_PARAMETER
+ *              AE_BAD_DATA         Invalid target throttling state.
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+/* TBD: Includes support for _real_ performance states (not just throttling). */
+
+ACPI_STATUS
+pr_perf_set_state (
+	PR_CONTEXT              *processor,
+	u32                     state)
+{
+	u32                     pblk_value = 0;
+	u32                     duty_mask = 0;
+	u32                     duty_cycle = 0;
+	u32                     i = 0;
+
+	if (!processor) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	if (state > (processor->performance.state_count - 1)) {
+		return(AE_BAD_DATA);
+	}
+
+	if (processor->performance.state_count == 1) {
+		return(AE_OK);
+	}
+
+	/*
+	 * Calculate Duty Cycle/Mask:
+	 * --------------------------
+	 * Note that we don't support duty_cycle values that span bit 4.
+	 */
+	if (state) {
+		duty_cycle = processor->performance.state_count - state;
+		duty_cycle <<= acpi_fadt.duty_offset;
+	}
+	else {
+		duty_cycle = 0;
+	}
+
+	duty_mask = ~((u32)(processor->performance.state_count - 1));
+	for (i=0; i<acpi_fadt.duty_offset; i++) {
+		duty_mask <<= acpi_fadt.duty_offset;
+		duty_mask += 1;
+	}
+
+	/*
+	 * Disable Throttling:
+	 * -------------------
+	 * Got to turn it off before you can change the duty_cycle value.
+	 * Throttling is disabled by writing a 0 to bit 4.
+	 */
+	pblk_value = acpi_os_in32(processor->pblk.address);
+	if (pblk_value & 0x00000010) {
+		pblk_value &= 0xFFFFFFEF;
+		acpi_os_out32(processor->pblk.address, pblk_value);
+	}
+
+	/*
+	 * Set Duty Cycle:
+	 * ---------------
+	 * Mask off the old duty_cycle value, mask in the new.
+	 */
+	pblk_value &= duty_mask;
+	pblk_value |= duty_cycle;
+	acpi_os_out32(processor->pblk.address, pblk_value);
+
+	/*
+	 * Enable Throttling:
+	 * ------------------
+	 * But only for non-zero (non-100% performance) states.
+	 */
+	if (state) {
+		pblk_value |= 0x00000010;
+		acpi_os_out32(processor->pblk.address, pblk_value);
+	}
+
+	return(AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_set_limit
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+pr_perf_set_limit (
+	PR_CONTEXT              *processor,
+	u32                     limit)
+{
+	ACPI_STATUS		status = AE_OK;
+	PR_PERFORMANCE		*performance = NULL;
+
+	if (!processor) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	performance = &(processor->performance);
+
+	/*
+	 * Set Limit:
+	 * ----------
+	 * TBD:  Properly manage thermal and power limits (only set
+	 *	 performance state iff...).
+	 */
+	switch (limit) {
+
+	case PR_PERF_DEC:
+		if (performance->active_state <
+			(performance->state_count-1)) {
+			status = pr_perf_set_state(processor,
+				(performance->active_state-1));
+		}
+		break;
+
+	case PR_PERF_INC:
+		if (performance->active_state > 0) {
+			status = pr_perf_set_state(processor,
+				(performance->active_state+1));
+		}
+		break;
+
+	case PR_PERF_MAX:
+		if (performance->active_state != 0) {
+			status = pr_perf_set_state(processor, 0);
+		}
+		break;
+
+	default:
+		return(AE_BAD_DATA);
+		break;
+	}
+
+	if (ACPI_SUCCESS(status)) {
+		performance->thermal_limit = limit;
+	}
+
+	return(status);
+}
+
+
+/****************************************************************************
+ *                             External Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_add_device
+ *
+ * PARAMETERS:  processor		Our processor-specific context.
+ *
+ * RETURN:      AE_OK
+ *              AE_BAD_PARAMETER
+ *
+ * DESCRIPTION: Calculates the number of throttling states and the state
+ *              performance/power values.
+ *
+ ****************************************************************************/
+
+/* TBD: Support duty_cycle values that span bit 4. */
+
+ACPI_STATUS
+pr_perf_add_device (
+	PR_CONTEXT              *processor)
+{
+	ACPI_STATUS             status = AE_OK;
+	u32                     i = 0;
+	u32                     performance_step = 0;
+	u32                     percentage = 0;
+
+	if (!processor) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	/*
+	 * Valid PBLK?
+	 * -----------
+	 * For SMP it is common to have the first (boot) processor have a
+	 * valid PBLK while all others do not -- which implies that
+	 * throttling has system-wide effects (duty_cycle programmed into
+	 * the chipset effects all processors).
+	 */
+	if ((processor->pblk.length < 6) || !processor->pblk.address) {
+		processor->performance.state_count = 1;
+	}
+
+	/*
+	 * Valid Duty Offset/Width?
+	 * ------------------------
+	 * We currently only support duty_cycle values that fall within
+	 * bits 0-3, as things get complicated when this value spans bit 4
+	 * (the throttling enable/disable bit).
+	 */
+	else if ((acpi_fadt.duty_offset + acpi_fadt.duty_width) > 4) {
+		processor->performance.state_count = 1;
+	}
+
+	/*
+	 * Compute State Count:
+	 * --------------------
+	 * The number of throttling states is computed as 2^duty_width,
+	 * but limited by PR_MAX_THROTTLE_STATES.  Note that a duty_width
+	 * of zero results is one throttling state (100%).
+	 */
+	else {
+		processor->performance.state_count =
+			POWER_OF_2[acpi_fadt.duty_width];
+	}
+
+	if (processor->performance.state_count > PR_MAX_THROTTLE_STATES) {
+		processor->performance.state_count = PR_MAX_THROTTLE_STATES;
+	}
+
+	/*
+	 * Compute State Values:
+	 * ---------------------
+	 * Note that clock throttling displays a linear power/performance
+	 * relationship (at 50% performance the CPU will consume 50% power).
+	 */
+	performance_step = (1000 / processor->performance.state_count);
+
+	for (i=0; i<processor->performance.state_count; i++) {
+		percentage = (1000 - (performance_step * i))/10;
+		processor->performance.state[i].performance = percentage;
+		processor->performance.state[i].power = percentage;
+	}
+
+	/*
+	 * Get Current State:
+	 * ------------------
+	 */
+	status = pr_perf_get_state(processor,
+		&(processor->performance.active_state));
+
+	return(status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    pr_perf_remove_device
+ *
+ * PARAMETERS:
+ *
+ * RETURN:	
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+pr_perf_remove_device (
+	PR_CONTEXT              *processor)
+{
+	ACPI_STATUS             status = AE_OK;
+
+	if (!processor) {
+		return(AE_BAD_PARAMETER);
+	}
+
+	MEMSET(&(processor->performance), 0, sizeof(PR_PERFORMANCE));
+
+	return(status);
+}
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)