aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/thermal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/thermal.c')
-rw-r--r--drivers/acpi/thermal.c143
1 files changed, 129 insertions, 14 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 5a62de1b7f2a..1e06159fd9c4 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -33,6 +33,7 @@
33 33
34#include <linux/kernel.h> 34#include <linux/kernel.h>
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/dmi.h>
36#include <linux/init.h> 37#include <linux/init.h>
37#include <linux/types.h> 38#include <linux/types.h>
38#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
@@ -74,10 +75,26 @@ MODULE_AUTHOR("Paul Diefenbaugh");
74MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); 75MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
75MODULE_LICENSE("GPL"); 76MODULE_LICENSE("GPL");
76 77
78static int act;
79module_param(act, int, 0644);
80MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.\n");
81
77static int tzp; 82static int tzp;
78module_param(tzp, int, 0); 83module_param(tzp, int, 0444);
79MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); 84MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
80 85
86static int nocrt;
87module_param(nocrt, int, 0);
88MODULE_PARM_DESC(nocrt, "Set to disable action on ACPI thermal zone critical and hot trips.\n");
89
90static int off;
91module_param(off, int, 0);
92MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.\n");
93
94static int psv;
95module_param(psv, int, 0644);
96MODULE_PARM_DESC(psv, "Disable or override all passive trip points.\n");
97
81static int acpi_thermal_add(struct acpi_device *device); 98static int acpi_thermal_add(struct acpi_device *device);
82static int acpi_thermal_remove(struct acpi_device *device, int type); 99static int acpi_thermal_remove(struct acpi_device *device, int type);
83static int acpi_thermal_resume(struct acpi_device *device); 100static int acpi_thermal_resume(struct acpi_device *device);
@@ -339,9 +356,16 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
339 356
340 /* Passive: Processors (optional) */ 357 /* Passive: Processors (optional) */
341 358
342 status = 359 if (psv == -1) {
343 acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, 360 status = AE_SUPPORT;
344 &tz->trips.passive.temperature); 361 } else if (psv > 0) {
362 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
363 status = AE_OK;
364 } else {
365 status = acpi_evaluate_integer(tz->device->handle,
366 "_PSV", NULL, &tz->trips.passive.temperature);
367 }
368
345 if (ACPI_FAILURE(status)) { 369 if (ACPI_FAILURE(status)) {
346 tz->trips.passive.flags.valid = 0; 370 tz->trips.passive.flags.valid = 0;
347 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); 371 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
@@ -386,11 +410,33 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
386 410
387 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 411 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
388 412
389 status = 413 if (act == -1)
390 acpi_evaluate_integer(tz->device->handle, name, NULL, 414 break; /* disable all active trip points */
391 &tz->trips.active[i].temperature); 415
392 if (ACPI_FAILURE(status)) 416 status = acpi_evaluate_integer(tz->device->handle,
417 name, NULL, &tz->trips.active[i].temperature);
418
419 if (ACPI_FAILURE(status)) {
420 if (i == 0) /* no active trip points */
421 break;
422 if (act <= 0) /* no override requested */
423 break;
424 if (i == 1) { /* 1 trip point */
425 tz->trips.active[0].temperature =
426 CELSIUS_TO_KELVIN(act);
427 } else { /* multiple trips */
428 /*
429 * Don't allow override higher than
430 * the next higher trip point
431 */
432 tz->trips.active[i - 1].temperature =
433 (tz->trips.active[i - 2].temperature <
434 CELSIUS_TO_KELVIN(act) ?
435 tz->trips.active[i - 2].temperature :
436 CELSIUS_TO_KELVIN(act));
437 }
393 break; 438 break;
439 }
394 440
395 name[2] = 'L'; 441 name[2] = 'L';
396 status = 442 status =
@@ -427,7 +473,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz)
427 473
428static int acpi_thermal_critical(struct acpi_thermal *tz) 474static int acpi_thermal_critical(struct acpi_thermal *tz)
429{ 475{
430 if (!tz || !tz->trips.critical.flags.valid) 476 if (!tz || !tz->trips.critical.flags.valid || nocrt)
431 return -EINVAL; 477 return -EINVAL;
432 478
433 if (tz->temperature >= tz->trips.critical.temperature) { 479 if (tz->temperature >= tz->trips.critical.temperature) {
@@ -449,7 +495,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
449 495
450static int acpi_thermal_hot(struct acpi_thermal *tz) 496static int acpi_thermal_hot(struct acpi_thermal *tz)
451{ 497{
452 if (!tz || !tz->trips.hot.flags.valid) 498 if (!tz || !tz->trips.hot.flags.valid || nocrt)
453 return -EINVAL; 499 return -EINVAL;
454 500
455 if (tz->temperature >= tz->trips.hot.temperature) { 501 if (tz->temperature >= tz->trips.hot.temperature) {
@@ -824,12 +870,14 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
824 goto end; 870 goto end;
825 871
826 if (tz->trips.critical.flags.valid) 872 if (tz->trips.critical.flags.valid)
827 seq_printf(seq, "critical (S5): %ld C\n", 873 seq_printf(seq, "critical (S5): %ld C%s",
828 KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); 874 KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
875 nocrt ? " <disabled>\n" : "\n");
829 876
830 if (tz->trips.hot.flags.valid) 877 if (tz->trips.hot.flags.valid)
831 seq_printf(seq, "hot (S4): %ld C\n", 878 seq_printf(seq, "hot (S4): %ld C%s",
832 KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); 879 KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
880 nocrt ? " <disabled>\n" : "\n");
833 881
834 if (tz->trips.passive.flags.valid) { 882 if (tz->trips.passive.flags.valid) {
835 seq_printf(seq, 883 seq_printf(seq,
@@ -1281,11 +1329,78 @@ static int acpi_thermal_resume(struct acpi_device *device)
1281 return AE_OK; 1329 return AE_OK;
1282} 1330}
1283 1331
1332#ifdef CONFIG_DMI
1333static int thermal_act(struct dmi_system_id *d) {
1334
1335 if (act == 0) {
1336 printk(KERN_NOTICE "ACPI: %s detected: "
1337 "disabling all active thermal trip points\n", d->ident);
1338 act = -1;
1339 }
1340 return 0;
1341}
1342static int thermal_tzp(struct dmi_system_id *d) {
1343
1344 if (tzp == 0) {
1345 printk(KERN_NOTICE "ACPI: %s detected: "
1346 "enabling thermal zone polling\n", d->ident);
1347 tzp = 300; /* 300 dS = 30 Seconds */
1348 }
1349 return 0;
1350}
1351static int thermal_psv(struct dmi_system_id *d) {
1352
1353 if (psv == 0) {
1354 printk(KERN_NOTICE "ACPI: %s detected: "
1355 "disabling all passive thermal trip points\n", d->ident);
1356 psv = -1;
1357 }
1358 return 0;
1359}
1360
1361static struct dmi_system_id thermal_dmi_table[] __initdata = {
1362 /*
1363 * Award BIOS on this AOpen makes thermal control almost worthless.
1364 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1365 */
1366 {
1367 .callback = thermal_act,
1368 .ident = "AOpen i915GMm-HFS",
1369 .matches = {
1370 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1371 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1372 },
1373 },
1374 {
1375 .callback = thermal_psv,
1376 .ident = "AOpen i915GMm-HFS",
1377 .matches = {
1378 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1379 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1380 },
1381 },
1382 {
1383 .callback = thermal_tzp,
1384 .ident = "AOpen i915GMm-HFS",
1385 .matches = {
1386 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1387 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1388 },
1389 },
1390 {}
1391};
1392#endif /* CONFIG_DMI */
1393
1284static int __init acpi_thermal_init(void) 1394static int __init acpi_thermal_init(void)
1285{ 1395{
1286 int result = 0; 1396 int result = 0;
1287 1397
1398 dmi_check_system(thermal_dmi_table);
1288 1399
1400 if (off) {
1401 printk(KERN_NOTICE "ACPI: thermal control disabled\n");
1402 return -ENODEV;
1403 }
1289 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); 1404 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1290 if (!acpi_thermal_dir) 1405 if (!acpi_thermal_dir)
1291 return -ENODEV; 1406 return -ENODEV;