1/**************************************************************************** 2 * 3 * Module Name: tzpolicy.c - 4 * $Revision: 1.1.1.1 $ 5 * 6 ****************************************************************************/ 7 8/* 9 * Copyright (C) 2000, 2001 Andrew Grover 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26/* 27 * TBD: 1. Support performance-limit control for non-processor devices 28 * (those listed in _TZD, e.g. graphics). 29 */ 30 31#include <linux/proc_fs.h> 32#include <linux/sysctl.h> 33#include <linux/pm.h> 34 35#include <acpi.h> 36#include <bm.h> 37#include "tz.h" 38 39 40#define _COMPONENT ACPI_THERMAL 41 MODULE_NAME ("tzpolicy") 42 43 44/**************************************************************************** 45 * Globals 46 ****************************************************************************/ 47 48void 49tz_policy_run ( 50 unsigned long data); 51 52 53/**************************************************************************** 54 * Internal Functions 55 ****************************************************************************/ 56 57acpi_status 58set_performance_limit ( 59 BM_HANDLE device_handle, 60 u32 flag) 61{ 62 acpi_status status; 63 BM_REQUEST request; 64 65 request.status = AE_OK; 66 request.handle = device_handle; 67 request.command = PR_COMMAND_SET_PERF_LIMIT; 68 request.buffer.length = sizeof(u32); 69 request.buffer.pointer = &flag; 70 71 status = bm_request(&request); 72 73 if (ACPI_FAILURE(status)) 74 return status; 75 else 76 return request.status; 77} 78 79 80/**************************************************************************** 81 * 82 * FUNCTION: tz_policy_critical 83 * 84 * PARAMETERS: 85 * 86 * RETURN: 87 * 88 * DESCRIPTION: 89 * 90 ****************************************************************************/ 91 92acpi_status 93tz_policy_critical( 94 TZ_CONTEXT *tz) 95{ 96 FUNCTION_TRACE("tz_policy_critical"); 97 98 if (!tz) { 99 return_ACPI_STATUS(AE_BAD_PARAMETER); 100 } 101 102 if (tz->policy.temperature >= tz->policy.thresholds.critical.temperature) { 103 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Critical (S5) threshold reached.\n")); 104 /* TBD: Need method for shutting down system. */ 105 } 106 107 return_ACPI_STATUS(AE_OK); 108} 109 110 111/**************************************************************************** 112 * 113 * FUNCTION: tz_policy_hot 114 * 115 * PARAMETERS: 116 * 117 * RETURN: 118 * 119 * DESCRIPTION: 120 * 121 ****************************************************************************/ 122 123acpi_status 124tz_policy_hot( 125 TZ_CONTEXT *tz) 126{ 127 FUNCTION_TRACE("tz_policy_hot"); 128 129 if (!tz || !tz->policy.thresholds.hot.is_valid) { 130 return_ACPI_STATUS(AE_BAD_PARAMETER); 131 } 132 133 if (tz->policy.temperature >= tz->policy.thresholds.hot.temperature) { 134 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Critical (S4) threshold reached.\n")); 135 /* TBD: Need method for invoking OS-level critical suspend. */ 136 } 137 138 return_ACPI_STATUS(AE_OK); 139} 140 141 142/**************************************************************************** 143 * 144 * FUNCTION: tz_policy_passive 145 * 146 * PARAMETERS: 147 * 148 * RETURN: 149 * 150 * DESCRIPTION: 151 * 152 ****************************************************************************/ 153 154acpi_status 155tz_policy_passive( 156 TZ_CONTEXT *tz) 157{ 158 TZ_PASSIVE_THRESHOLD *passive = NULL; 159 static u32 last_temperature = 0; 160 s32 trend = 0; 161 u32 i = 0; 162 163 FUNCTION_TRACE("tz_policy_passive"); 164 165 if (!tz || !tz->policy.thresholds.passive.is_valid) { 166 return_ACPI_STATUS(AE_BAD_PARAMETER); 167 } 168 169 passive = &(tz->policy.thresholds.passive); 170 171 if (tz->policy.temperature >= passive->temperature) { 172 /* 173 * Thermal trend? 174 * -------------- 175 * Using the passive cooling equation (see the ACPI 176 * Specification), calculate the current thermal trend 177 * (a.k.a. performance delta). 178 */ 179 trend = passive->tc1 * (tz->policy.temperature - last_temperature) + passive->tc2 * (tz->policy.temperature - passive->temperature); 180 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "trend[%d] = TC1[%d]*(temp[%d]-last[%d]) + TC2[%d]*(temp[%d]-passive[%d])\n", trend, passive->tc1, tz->policy.temperature, last_temperature, passive->tc2, tz->policy.temperature, passive->temperature)); 181 182 last_temperature = tz->policy.temperature; 183 184 /* 185 * Heating Up? 186 * ----------- 187 * Decrease thermal performance limit on all passive 188 * cooling devices (processors). 189 */ 190 if (trend > 0) { 191 for (i=0; i<passive->devices.count; i++) 192 set_performance_limit(passive->devices.handles[i], PR_PERF_DEC); 193 } 194 /* 195 * Cooling Off? 196 * ------------ 197 * Increase thermal performance limit on all passive 198 * cooling devices (processors). 199 */ 200 else if (trend < 0) { 201 for (i=0; i<passive->devices.count; i++) 202 set_performance_limit(passive->devices.handles[i], PR_PERF_INC); 203 } 204 } 205 206 return_ACPI_STATUS(AE_OK); 207} 208 209 210/**************************************************************************** 211 * 212 * FUNCTION: tz_policy_active 213 * 214 * PARAMETERS: 215 * 216 * RETURN: 217 * 218 * DESCRIPTION: 219 * 220 ****************************************************************************/ 221 222acpi_status 223tz_policy_active( 224 TZ_CONTEXT *tz) 225{ 226 acpi_status status = AE_OK; 227 TZ_ACTIVE_THRESHOLD *active = NULL; 228 u32 i,j = 0; 229 230 FUNCTION_TRACE("tz_policy_active"); 231 232 if (!tz || !tz->policy.thresholds.active[0].is_valid) { 233 return_ACPI_STATUS(AE_BAD_PARAMETER); 234 } 235 236 for (i=0; i<TZ_MAX_ACTIVE_THRESHOLDS; i++) { 237 238 active = &(tz->policy.thresholds.active[i]); 239 if (!active || !active->is_valid) 240 break; 241 242 /* 243 * Above Threshold? 244 * ---------------- 245 * If not already enabled, turn ON all cooling devices 246 * associated with this active threshold. 247 */ 248 if ((tz->policy.temperature >= active->temperature) && (active->cooling_state != TZ_COOLING_ENABLED)) { 249 for (j = 0; j < active->devices.count; j++) { 250 status = bm_set_device_power_state(active->devices.handles[j], ACPI_STATE_D0); 251 if (ACPI_SUCCESS(status)) { 252 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Cooling device [%02x] now ON.\n", active->devices.handles[j])); 253 } 254 else { 255 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to turn ON cooling device [%02x].\n", active->devices.handles[j])); 256 } 257 } 258 active->cooling_state = TZ_COOLING_ENABLED; 259 } 260 /* 261 * Below Threshold? 262 * ---------------- 263 * Turn OFF all cooling devices associated with this 264 * threshold. Note that by checking "if not disabled" we 265 * turn off all cooling devices for thresholds in the 266 * TZ_COOLING_STATE_UNKNOWN state, useful as a level-set 267 * during the first pass. 268 */ 269 else if (active->cooling_state != TZ_COOLING_DISABLED) { 270 for (j = 0; j < active->devices.count; j++) { 271 status = bm_set_device_power_state(active->devices.handles[j], ACPI_STATE_D3); 272 if (ACPI_SUCCESS(status)) { 273 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Cooling device [%02x] now OFF.\n", active->devices.handles[j])); 274 } 275 else { 276 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unable to turn OFF cooling device [%02x].\n", active->devices.handles[j])); 277 } 278 } 279 active->cooling_state = TZ_COOLING_DISABLED; 280 } 281 } 282 283 return_ACPI_STATUS(AE_OK); 284} 285 286 287/**************************************************************************** 288 * 289 * FUNCTION: tz_policy_check 290 * 291 * PARAMETERS: 292 * 293 * RETURN: 294 * 295 * DESCRIPTION: Note that this function will get called whenever: 296 * 1. A thermal event occurs. 297 * 2. The polling/sampling time period expires. 298 * 299 ****************************************************************************/ 300 301void 302tz_policy_check ( 303 void *context) 304{ 305 acpi_status status = AE_OK; 306 TZ_CONTEXT *tz = NULL; 307 TZ_POLICY *policy = NULL; 308 TZ_THRESHOLDS *thresholds = NULL; 309 u32 previous_temperature = 0; 310 u32 previous_state = 0; 311 u32 active_index = 0; 312 u32 i = 0; 313 u32 sleep_time = 0; 314 315 FUNCTION_TRACE("tz_policy_check"); 316 317 if (!context) { 318 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); 319 return_VOID; 320 } 321 322 tz = (TZ_CONTEXT*)context; 323 policy = &(tz->policy); 324 thresholds = &(tz->policy.thresholds); 325 326 /* 327 * Preserve Previous State: 328 * ------------------------ 329 */ 330 previous_temperature = tz->policy.temperature; 331 previous_state = tz->policy.state; 332 333 /* 334 * Get Temperature: 335 * ---------------- 336 */ 337 status = tz_get_temperature(tz); 338 if (ACPI_FAILURE(status)) { 339 return_VOID; 340 } 341 342 /* 343 * Calculate State: 344 * ---------------- 345 */ 346 policy->state = TZ_STATE_OK; 347 348 /* Critical? */ 349 if (policy->temperature >= thresholds->critical.temperature) 350 policy->state |= TZ_STATE_CRITICAL; 351 352 /* Hot? */ 353 if ((thresholds->hot.is_valid) && (policy->temperature >= thresholds->hot.temperature)) 354 policy->state |= TZ_STATE_CRITICAL; 355 356 /* Passive? */ 357 if ((thresholds->passive.is_valid) && (policy->temperature >= thresholds->passive.temperature)) 358 policy->state |= TZ_STATE_PASSIVE; 359 360 /* Active? */ 361 if (thresholds->active[0].is_valid) { 362 for (i=0; i<TZ_MAX_ACTIVE_THRESHOLDS; i++) { 363 if ((thresholds->active[i].is_valid) && (policy->temperature >= thresholds->active[i].temperature)) { 364 policy->state |= TZ_STATE_ACTIVE; 365 if (i > active_index) 366 active_index = i; 367 } 368 } 369 policy->state |= active_index; 370 } 371 372 /* 373 * Invoke Policy: 374 * -------------- 375 * Note that policy must be invoked both when 'going into' a 376 * policy state (e.g. to allow fans to be turned on) and 'going 377 * out of' a policy state (e.g. to allow fans to be turned off); 378 * thus we must preserve the previous state. 379 */ 380 if (policy->state & TZ_STATE_CRITICAL) 381 tz_policy_critical(tz); 382 if (policy->state & TZ_STATE_HOT) 383 tz_policy_hot(tz); 384 if ((policy->state & TZ_STATE_PASSIVE) || (previous_state & TZ_STATE_PASSIVE)) 385 tz_policy_passive(tz); 386 if ((policy->state & TZ_STATE_ACTIVE) || (previous_state & TZ_STATE_ACTIVE)) 387 tz_policy_active(tz); 388 389 /* 390 * Calculate Sleep Time: 391 * --------------------- 392 * If we're in the passive state, use _TSP's value. Otherwise 393 * use _TZP or the OS's default polling frequency. If no polling 394 * frequency is specified then we'll wait forever (that is, until 395 * a thermal event occurs -- e.g. never poll). Note that _TSP 396 * and _TZD values are given in 1/10th seconds. 397 */ 398 if (policy->state & TZ_STATE_PASSIVE) 399 sleep_time = thresholds->passive.tsp * 100; 400 else if (policy->polling_freq > 0) 401 sleep_time = policy->polling_freq * 100; 402 else 403 sleep_time = WAIT_FOREVER; 404 405 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Thermal_zone[%02x]: temperature[%d] state[%08x]\n", tz->device_handle, policy->temperature, policy->state)); 406 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling next poll in [%d]ms.\n", sleep_time)); 407 408 /* 409 * Schedule Next Poll: 410 * ------------------- 411 */ 412 if (sleep_time < WAIT_FOREVER) { 413 if (timer_pending(&(policy->timer))) 414 mod_timer(&(policy->timer), (HZ*sleep_time)/1000); 415 else { 416 policy->timer.data = (unsigned long)tz; 417 policy->timer.function = tz_policy_run; 418 policy->timer.expires = jiffies + (HZ*sleep_time)/1000; 419 add_timer(&(policy->timer)); 420 } 421 } 422 else { 423 if (timer_pending(&(policy->timer))) 424 del_timer(&(policy->timer)); 425 } 426 427 return_VOID; 428} 429 430 431/**************************************************************************** 432 * 433 * FUNCTION: tz_policy_run 434 * 435 * PARAMETERS: 436 * 437 * RETURN: 438 * 439 * DESCRIPTION: 440 * 441 ****************************************************************************/ 442 443 444void 445tz_policy_run ( 446 unsigned long data) 447{ 448 acpi_status status = AE_OK; 449 450 FUNCTION_TRACE("tz_policy_run"); 451 452 if (!data) { 453 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); 454 return_VOID; 455 } 456 457 /* 458 * Defer to Non-Interrupt Level: 459 * ----------------------------- 460 * Note that all Linux kernel timers run at interrupt-level (ack!). 461 */ 462 status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, tz_policy_check, (void*)data); 463 if (ACPI_FAILURE(status)) { 464 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Error invoking thermal policy.\n")); 465 } 466 467 return_VOID; 468} 469 470 471/**************************************************************************** 472 * 473 * FUNCTION: tz_policy_add_device 474 * 475 * PARAMETERS: 476 * 477 * RETURN: 478 * 479 * DESCRIPTION: 480 * 481 ****************************************************************************/ 482 483acpi_status 484tz_policy_add_device ( 485 TZ_CONTEXT *tz) 486{ 487 acpi_status status = AE_OK; 488 TZ_THRESHOLDS *thresholds = NULL; 489 u32 i,j = 0; 490 491 FUNCTION_TRACE("tz_policy_add_device"); 492 493 if (!tz) { 494 return_ACPI_STATUS(AE_BAD_PARAMETER); 495 } 496 497 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding policy for thermal zone [%02x].\n", tz->device_handle)); 498 499 /* 500 * Get Thresholds: 501 * --------------- 502 */ 503 status = tz_get_thresholds(tz); 504 if (ACPI_FAILURE(status)) { 505 return_ACPI_STATUS(status); 506 } 507 508 /* 509 * Initialize Policies: 510 * -------------------- 511 */ 512 if (tz->policy.thresholds.passive.is_valid) { 513 for (i=0; i<tz->policy.thresholds.passive.devices.count; i++) 514 set_performance_limit(tz->policy.thresholds.passive.devices.handles[i], PR_PERF_MAX); 515 tz_policy_passive(tz); 516 } 517 if (tz->policy.thresholds.active[0].is_valid) 518 tz_policy_active(tz); 519 520 /* 521 * Initialize Policy Timer: 522 * ------------------------ 523 */ 524 init_timer(&(tz->policy.timer)); 525 526 /* 527 * Start Policy: 528 * ------------- 529 * Run an initial check using this zone's policy. 530 */ 531 tz_policy_check(tz); 532 533 return_ACPI_STATUS(AE_OK); 534} 535 536 537/***************************************************************************** 538 * 539 * FUNCTION: tz_policy_remove_device 540 * 541 * PARAMETERS: 542 * 543 * RETURN: 544 * 545 * DESCRIPTION: 546 * 547 ****************************************************************************/ 548 549acpi_status 550tz_policy_remove_device( 551 TZ_CONTEXT *tz) 552{ 553 u32 i = 0; 554 555 FUNCTION_TRACE("tz_remove_device"); 556 557 if (!tz) { 558 return_ACPI_STATUS(AE_BAD_PARAMETER); 559 } 560 561 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing policy for thermal zone [%02x].\n", tz->device_handle)); 562 563 /* 564 * Delete the thermal zone policy timer entry, if exists. 565 */ 566 if (timer_pending(&(tz->policy.timer))) 567 del_timer(&(tz->policy.timer)); 568 569 /* 570 * Reset thermal performance limit on all processors back to max. 571 */ 572 if (tz->policy.thresholds.passive.is_valid) { 573 for (i=0; i<tz->policy.thresholds.passive.devices.count; i++) 574 set_performance_limit(tz->policy.thresholds.passive.devices.handles[i], PR_PERF_MAX); 575 } 576 577 return_ACPI_STATUS(AE_OK); 578} 579