diff options
| -rw-r--r-- | drivers/acpi/processor_throttling.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index d6780f41d28c..18a873a55256 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -45,6 +45,14 @@ | |||
| 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 46 | ACPI_MODULE_NAME("processor_throttling"); | 46 | ACPI_MODULE_NAME("processor_throttling"); |
| 47 | 47 | ||
| 48 | struct throttling_tstate { | ||
| 49 | unsigned int cpu; /* cpu nr */ | ||
| 50 | int target_state; /* target T-state */ | ||
| 51 | }; | ||
| 52 | |||
| 53 | #define THROTTLING_PRECHANGE (1) | ||
| 54 | #define THROTTLING_POSTCHANGE (2) | ||
| 55 | |||
| 48 | static int acpi_processor_get_throttling(struct acpi_processor *pr); | 56 | static int acpi_processor_get_throttling(struct acpi_processor *pr); |
| 49 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | 57 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); |
| 50 | 58 | ||
| @@ -196,6 +204,70 @@ void acpi_processor_throttling_init(void) | |||
| 196 | return; | 204 | return; |
| 197 | } | 205 | } |
| 198 | 206 | ||
| 207 | static int acpi_processor_throttling_notifier(unsigned long event, void *data) | ||
| 208 | { | ||
| 209 | struct throttling_tstate *p_tstate = data; | ||
| 210 | struct acpi_processor *pr; | ||
| 211 | unsigned int cpu ; | ||
| 212 | int target_state; | ||
| 213 | struct acpi_processor_limit *p_limit; | ||
| 214 | struct acpi_processor_throttling *p_throttling; | ||
| 215 | |||
| 216 | cpu = p_tstate->cpu; | ||
| 217 | pr = processors[cpu]; | ||
| 218 | if (!pr) { | ||
| 219 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n")); | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | if (!pr->flags.throttling) { | ||
| 223 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is " | ||
| 224 | "unsupported on CPU %d\n", cpu)); | ||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | target_state = p_tstate->target_state; | ||
| 228 | p_throttling = &(pr->throttling); | ||
| 229 | switch (event) { | ||
| 230 | case THROTTLING_PRECHANGE: | ||
| 231 | /* | ||
| 232 | * Prechange event is used to choose one proper t-state, | ||
| 233 | * which meets the limits of thermal, user and _TPC. | ||
| 234 | */ | ||
| 235 | p_limit = &pr->limit; | ||
| 236 | if (p_limit->thermal.tx > target_state) | ||
| 237 | target_state = p_limit->thermal.tx; | ||
| 238 | if (p_limit->user.tx > target_state) | ||
| 239 | target_state = p_limit->user.tx; | ||
| 240 | if (pr->throttling_platform_limit > target_state) | ||
| 241 | target_state = pr->throttling_platform_limit; | ||
| 242 | if (target_state >= p_throttling->state_count) { | ||
| 243 | printk(KERN_WARNING | ||
| 244 | "Exceed the limit of T-state \n"); | ||
| 245 | target_state = p_throttling->state_count - 1; | ||
| 246 | } | ||
| 247 | p_tstate->target_state = target_state; | ||
| 248 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:" | ||
| 249 | "target T-state of CPU %d is T%d\n", | ||
| 250 | cpu, target_state)); | ||
| 251 | break; | ||
| 252 | case THROTTLING_POSTCHANGE: | ||
| 253 | /* | ||
| 254 | * Postchange event is only used to update the | ||
| 255 | * T-state flag of acpi_processor_throttling. | ||
| 256 | */ | ||
| 257 | p_throttling->state = target_state; | ||
| 258 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:" | ||
| 259 | "CPU %d is switched to T%d\n", | ||
| 260 | cpu, target_state)); | ||
| 261 | break; | ||
| 262 | default: | ||
| 263 | printk(KERN_WARNING | ||
| 264 | "Unsupported Throttling notifier event\n"); | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | |||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 199 | /* | 271 | /* |
| 200 | * _TPC - Throttling Present Capabilities | 272 | * _TPC - Throttling Present Capabilities |
| 201 | */ | 273 | */ |
