# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/05 17:39:51-05:00 len.brown@intel.com # [ACPI] Allow limiting idle C-States. # # Useful to workaround C3 ipw2100 packet loss # and resonating noises heard on some laptops. # # For static processor driver, boot cmdline: # processor.acpi_cstate_limit=2 # # For processor module, /etc/modprobe.conf: # options processor acpi_cstate_limit=2 # # For manual processor module load: # # modprobe processor acpi_cstate_limit=2 # # From kernel or kernel module: # #include # acpi_set_cstate_limit(2); # # Inspired by patches from Jos Delbar and Andi Kleen # Signed-off-by: Len Brown # # include/linux/acpi.h # 2004/11/05 17:39:45-05:00 len.brown@intel.com +26 -0 # define API to set and get acpi_cstate_limit # # drivers/acpi/processor.c # 2004/11/05 17:39:45-05:00 len.brown@intel.com +10 -1 # set and obey acpi_cstate_limit # # drivers/acpi/osl.c # 2004/11/05 17:39:45-05:00 len.brown@intel.com +9 -0 # define acpi_cstate_limit # diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c 2004-11-05 17:40:07 -05:00 +++ b/drivers/acpi/osl.c 2004-11-05 17:40:07 -05:00 @@ -1078,3 +1078,12 @@ __setup("acpi_leave_gpes_disabled", acpi_leave_gpes_disabled_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:40:07 -05:00 +++ b/drivers/acpi/processor.c 2004-11-05 17:40:07 -05:00 @@ -459,8 +459,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; @@ -498,6 +499,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 @@ -2441,5 +2449,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:40:07 -05:00 +++ b/include/linux/acpi.h 2004-11-05 17:40:07 -05:00 @@ -471,4 +471,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*/