Commit 0ca608f6 authored by Len Brown's avatar Len Brown

[ACPI] Allow limiting idle C-States.

Useful to workaround C3 ipw2100 packet loss,
reducing noise or boot issues on some models.
http://bugme.osdl.org/show_bug.cgi?id=3549

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 <linux/acpi.h>
acpi_set_cstate_limit(2);

Inspired by patches from Jos Delbar and Andi Kleen
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 0b9aa6dd
......@@ -1078,3 +1078,12 @@ acpi_leave_gpes_disabled_setup(char *str)
__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);
......@@ -459,8 +459,9 @@ acpi_processor_idle (void)
* 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;
......@@ -497,6 +498,13 @@ acpi_processor_idle (void)
}
end:
/*
* Demote if current state exceeds acpi_cstate_limit
*/
if (pr->power.state > acpi_cstate_limit) {
next_state = acpi_cstate_limit;
}
/*
* New Cx State?
* -------------
......@@ -2441,5 +2449,6 @@ acpi_processor_exit (void)
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);
......@@ -471,4 +471,30 @@ static inline int acpi_blacklisted(void)
#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*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment