All of lore.kernel.org
 help / color / mirror / Atom feed
From: Len Brown <len.brown@intel.com>
To: Dominik Brodowski <linux@dominikbrodowski.de>
Cc: ACPI Developers <acpi-devel@lists.sourceforge.net>,
	cpufreq@www.linux.org.uk
Subject: Re: [PATCH 2.6] update passive cooling algorithm
Date: 28 Jan 2004 17:43:27 -0500	[thread overview]
Message-ID: <1075329807.2484.97.camel@dhcppc4> (raw)
In-Reply-To: <20040111211255.GA31105@dominikbrodowski.de>

Accepted into ACPI test tree
http://linux-acpi.bkbits.net/linux-acpi-test-2.6.0
http://linux-acpi.bkbits.net/linux-acpi-test-2.6.1
http://linux-acpi.bkbits.net/linux-acpi-test-2.6.2

This means it will be pulled into AKPM's mm tree on the next update.

thanks Dominik,
-Len

On Sun, 2004-01-11 at 16:12, Dominik Brodowski wrote:
> [Len, could you test and verify this patch, and push it to Linus, please?]
> 
> The current algorithm used by Linux ACPI for passive thermal management has
> two shortcomings:
> 
> - if increasing the CPU processing power as a thermal situation goes away,
>   throttling states are decreased later than performance states. This is
>   not wise -- it should be the opposite ordering of going "up".
> 
> - only if the ACPI CPUfreq driver is used, performance states are used.
>   A generalized approach would offer passive cooling even if the ACPI
>   P-States cpufreq driver cannot be used (faulty BIOS, FixedHW access, etc.)
> 
> The attached patch addresses these issues.
> 
>  drivers/acpi/processor.c |  182 +++++++++++++++++++++++++++++++++++++----------
>  1 files changed, 146 insertions(+), 36 deletions(-)
> 
> diff -ruN linux-original/drivers/acpi/processor.c linux/drivers/acpi/processor.c
> --- linux-original/drivers/acpi/processor.c	2004-01-11 20:51:17.000000000 +0100
> +++ linux/drivers/acpi/processor.c	2004-01-11 21:39:43.000000000 +0100
> @@ -1091,6 +1091,113 @@
>  }
>  
> 
> +#ifdef CONFIG_CPU_FREQ
> +
> +/* If a passive cooling situation is detected, primarily CPUfreq is used, as it
> + * offers (in most cases) voltage scaling in addition to frequency scaling, and
> + * thus a cubic (instead of linear) reduction of energy. Also, we allow for
> + * _any_ cpufreq driver and not only the acpi-cpufreq driver.
> + */
> +
> +static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
> +static unsigned int acpi_thermal_cpufreq_is_init = 0;
> +
> +
> +static int cpu_has_cpufreq(unsigned int cpu)
> +{
> +	struct cpufreq_policy policy;
> +	if (!acpi_thermal_cpufreq_is_init)
> +		return -ENODEV;
> +	if (!cpufreq_get_policy(&policy, cpu))
> +		return -ENODEV;
> +	return 0;
> +}
> +
> +
> +static int acpi_thermal_cpufreq_increase(unsigned int cpu)
> +{
> +	if (!cpu_has_cpufreq)
> +		return -ENODEV;
> +
> +	if (cpufreq_thermal_reduction_pctg[cpu] < 60) {
> +		cpufreq_thermal_reduction_pctg[cpu] += 20;
> +		cpufreq_update_policy(cpu);
> +		return 0;
> +	}
> +
> +	return -ERANGE;
> +}
> +
> +
> +static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
> +{
> +	if (!cpu_has_cpufreq)
> +		return -ENODEV;
> +
> +	if (cpufreq_thermal_reduction_pctg[cpu] >= 20) {
> +		cpufreq_thermal_reduction_pctg[cpu] -= 20;
> +		cpufreq_update_policy(cpu);
> +		return 0;
> +	}
> +
> +	return -ERANGE;
> +}
> +
> +
> +static int acpi_thermal_cpufreq_notifier(
> +	struct notifier_block *nb,
> +	unsigned long event,
> +	void *data)
> +{
> +	struct cpufreq_policy *policy = data;
> +	unsigned long max_freq = 0;
> +
> +	if (event != CPUFREQ_ADJUST)
> +		goto out;
> +
> +	max_freq = (policy->cpuinfo.max_freq * (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
> +
> +	cpufreq_verify_within_limits(policy, 0, max_freq);
> +
> + out:
> +	return 0;
> +}
> +
> +
> +static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
> +	.notifier_call = acpi_thermal_cpufreq_notifier,
> +};
> +
> +
> +static void acpi_thermal_cpufreq_init(void) {
> +	int i;
> +
> +	for (i=0; i<NR_CPUS; i++)
> +		cpufreq_thermal_reduction_pctg[i] = 0;
> +
> +	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
> +	if (!i)
> +		acpi_thermal_cpufreq_is_init = 1;
> +}
> +
> +static void acpi_thermal_cpufreq_exit(void) {
> +	if (acpi_thermal_cpufreq_is_init)
> +		cpufreq_unregister_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
> +
> +	acpi_thermal_cpufreq_is_init = 0;
> +}
> +
> +#else /* ! CONFIG_CPU_FREQ */
> +
> +static void acpi_thermal_cpufreq_init(void) { return; }
> +static void acpi_thermal_cpufreq_exit(void) { return; }
> +static int acpi_thermal_cpufreq_increase(unsigned int cpu) { return -ENODEV; }
> +static int acpi_thermal_cpufreq_decrease(unsigned int cpu) { return -ENODEV; }
> +
> +
> +#endif
> +
> +
>  int
>  acpi_processor_set_thermal_limit (
>  	acpi_handle		handle,
> @@ -1099,7 +1206,6 @@
>  	int			result = 0;
>  	struct acpi_processor	*pr = NULL;
>  	struct acpi_device	*device = NULL;
> -	int			px = 0;
>  	int			tx = 0;
>  
>  	ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
> @@ -1116,12 +1222,7 @@
>  	if (!pr)
>  		return_VALUE(-ENODEV);
>  
> -	if (!pr->flags.limit)
> -		return_VALUE(-ENODEV);
> -
>  	/* Thermal limits are always relative to the current Px/Tx state. */
> -	if (pr->flags.performance)
> -		pr->limit.thermal.px = pr->performance->state;
>  	if (pr->flags.throttling)
>  		pr->limit.thermal.tx = pr->throttling.state;
>  
> @@ -1130,26 +1231,27 @@
>  	 * performance state.
>  	 */
>  
> -	px = pr->limit.thermal.px;
>  	tx = pr->limit.thermal.tx;
>  
>  	switch (type) {
>  
>  	case ACPI_PROCESSOR_LIMIT_NONE:
> -		px = 0;
> +		do {
> +			result = acpi_thermal_cpufreq_decrease(pr->id);
> +		} while (!result);
>  		tx = 0;
>  		break;
>  
>  	case ACPI_PROCESSOR_LIMIT_INCREMENT:
> -		if (pr->flags.performance) {
> -			if (px == (pr->performance->state_count - 1))
> -				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
> +		/* if going up: P-states first, T-states later */
> +
> +		result = acpi_thermal_cpufreq_increase(pr->id);
> +		if (!result)
> +			goto end;
> +		else if (result == -ERANGE)
> +			ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
>  					"At maximum performance state\n"));
> -			else {
> -				px++;
> -				goto end;
> -			}
> -		}
> +
>  		if (pr->flags.throttling) {
>  			if (tx == (pr->throttling.state_count - 1))
>  				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
> @@ -1160,37 +1262,41 @@
>  		break;
>  
>  	case ACPI_PROCESSOR_LIMIT_DECREMENT:
> -		if (pr->flags.performance) {
> -			if (px == pr->performance_platform_limit)
> -				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
> -					"At minimum performance state\n"));
> -			else  {
> -				px--;
> -				goto end;
> -			}
> -		}
> +		/* if going down: T-states first, P-states later */
> +
>  		if (pr->flags.throttling) {
>  			if (tx == 0)
>  				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
>  					"At minimum throttling state\n"));
> -			else
> +			else {
>  				tx--;
> +				goto end;
> +			}
>  		}
> +
> +		result = acpi_thermal_cpufreq_decrease(pr->id);
> +		if (result == -ERANGE)
> +			ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
> +					"At minimum performance state\n"));
> +
>  		break;
>  	}
>  
>  end:
> -	pr->limit.thermal.px = px;
> -	pr->limit.thermal.tx = tx;
> -
> -	result = acpi_processor_apply_limit(pr);
> -	if (result)
> -		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
> -			"Unable to set thermal limit\n"));
> +	if (pr->flags.throttling) {
> +		pr->limit.thermal.px = 0;
> +		pr->limit.thermal.tx = tx;
>  
> -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
> -		pr->limit.thermal.px,
> -		pr->limit.thermal.tx));
> +		result = acpi_processor_apply_limit(pr);
> +		if (result)
> +			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
> +					  "Unable to set thermal limit\n"));
> +
> +		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
> +				  pr->limit.thermal.px,
> +				  pr->limit.thermal.tx));
> +	} else
> +		result = 0;
>  
>  	return_VALUE(result);
>  }
> @@ -1813,6 +1919,8 @@
>  		return_VALUE(-ENODEV);
>  	}
>  
> +	acpi_thermal_cpufreq_init();
> +
>  	return_VALUE(0);
>  }
>  
> @@ -1822,6 +1930,8 @@
>  {
>  	ACPI_FUNCTION_TRACE("acpi_processor_exit");
>  
> +	acpi_thermal_cpufreq_exit();
> +
>  	acpi_bus_unregister_driver(&acpi_processor_driver);
>  
>  	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);

  parent reply	other threads:[~2004-01-28 22:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-01-11 21:12 [PATCH 2.6] update passive cooling algorithm Dominik Brodowski
2004-01-12 15:46 ` Ducrot Bruno
2004-01-12 17:39   ` Dominik Brodowski
2004-01-12 19:11     ` Ducrot Bruno
2004-01-13  8:40       ` Dominik Brodowski
2004-01-15 12:18       ` [ACPI] " Pavel Machek
2004-01-15 13:42         ` Ducrot Bruno
2004-01-15 22:34           ` Pavel Machek
     [not found]             ` <20040115223425.GC18488-I/5MKhXcvmPrBKCeMvbIDA@public.gmane.org>
2004-01-16  1:14               ` Micha Feigin
2004-01-16 11:24             ` [ACPI] " Ducrot Bruno
2004-01-28 22:43 ` Len Brown [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-01-13  9:20 Dominik Brodowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1075329807.2484.97.camel@dhcppc4 \
    --to=len.brown@intel.com \
    --cc=acpi-devel@lists.sourceforge.net \
    --cc=cpufreq@www.linux.org.uk \
    --cc=linux@dominikbrodowski.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.