diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c 2004-11-05 17:51:14 -05:00 +++ b/drivers/acpi/osl.c 2004-11-05 17:51:14 -05:00 @@ -1100,3 +1100,12 @@ __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); +/* + * acpi_cstate_limit is defined in the base kernel so modules can + * change it w/o depending on the state of the processor module. + */ +unsigned int acpi_cstate_limit = ACPI_C_STATES_MAX; + + +EXPORT_SYMBOL(acpi_cstate_limit); + diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c 2004-11-05 17:51:14 -05:00 +++ b/drivers/acpi/processor.c 2004-11-05 17:51:14 -05:00 @@ -462,8 +462,9 @@ * Track the number of longs (time asleep is greater than threshold) * and promote when the count threshold is reached. Note that bus * mastering activity may prevent promotions. + * Do not promote above acpi_cstate_limit. */ - if (cx->promotion.state) { + if (cx->promotion.state && (cx->promotion.state <= acpi_cstate_limit)) { if (sleep_ticks > cx->promotion.threshold.ticks) { cx->promotion.count++; cx->demotion.count = 0; @@ -501,6 +502,13 @@ end: /* + * Demote if current state exceeds acpi_cstate_limit + */ + if (pr->power.state > acpi_cstate_limit) { + next_state = acpi_cstate_limit; + } + + /* * New Cx State? * ------------- * If we're going to start using a new Cx state we must clean up @@ -2492,5 +2500,6 @@ module_init(acpi_processor_init); module_exit(acpi_processor_exit); +module_param_named(acpi_cstate_limit, acpi_cstate_limit, uint, 0); EXPORT_SYMBOL(acpi_processor_set_thermal_limit); diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h 2004-11-05 17:51:14 -05:00 +++ b/include/linux/acpi.h 2004-11-05 17:51:14 -05:00 @@ -472,4 +472,30 @@ #endif /*!CONFIG_ACPI_INTERPRETER*/ +#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */ +#ifdef CONFIG_ACPI + +/* + * Set highest legal C-state + * 0: C0 okay, but not C1 + * 1: C1 okay, but not C2 + * 2: C2 okay, but not C3 etc. + */ + +extern unsigned int acpi_cstate_limit; + +static inline unsigned int acpi_get_cstate_limit(void) +{ + return acpi_cstate_limit; +} +static inline void acpi_set_cstate_limit(unsigned int new_limit) +{ + acpi_cstate_limit = new_limit; + return; +} +#else +static inline unsigned int acpi_get_cstate_limit(void) { return 0; } +static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; } +#endif + #endif /*_LINUX_ACPI_H*/